2015-02-09 7 views
5

मैं जंग जानने की कोशिश कर रही है, लेकिन केवल एक चीज मैं कर दीवार परिचित जूता पहनने का साधन (मेरे लिए) की कोशिश कर रहा अपने प्रकार प्रणाली में जावा अवधारणाओं मार रखना है। या Haskell अवधारणाओं को shoehorn करने की कोशिश करें, आदिसाझा परिवर्तनीय स्थिति का प्रतिनिधित्व कैसे करें?

मैं Player और कई Resource एस के साथ एक गेम लिखना चाहता हूं। प्रत्येक Resource एक Player के स्वामित्व में किया जा सकता है:

struct Player { 
    points: i32, 
} 

struct Resource<'a> { 
    owner: Option<&'a Player>, 
} 

fn main() { 
    let mut player = Player { points: 0 }; 
    let mut resources = Vec::new(); 
    resources.push(Resource { 
     owner: Some(&player), 
    }); 
    player.points = 30; 
} 

यह संकलन नहीं है, क्योंकि मैं खिलाड़ी के लिए संसाधन बिंदु नहीं हो सकता है, जबकि एक ही समय में इसे संशोधित:

error[E0506]: cannot assign to `player.points` because it is borrowed 
    --> src/main.rs:15:5 
    | 
13 |   owner: Some(&player), 
    |      ------ borrow of `player.points` occurs here 
14 |  }); 
15 |  player.points = 30; 
    |  ^^^^^^^^^^^^^^^^^^ assignment to borrowed `player.points` occurs here 

इसके अलावा , अगर ResourcePlayer करने के लिए एक परिवर्तनशील संदर्भ स्वामित्व, मैं भी दो Resource रों एक ही मालिक के साथ नहीं कर सकता है।

इस तरह के मामलों को हल करने के जंग तरीका क्या है?


मैं अपने प्रश्न oversimplified, और जब Shepmaster का जवाब यह करने के लिए एक सही जवाब है, यह है कि मैं क्या प्राप्त करना चाहता था नहीं है (क्योंकि जो मैंने पूछा क्या मैं वास्तव में नहीं पूछना चाहता था)। मैं इसे फिर से लिखने और अधिक संदर्भ जोड़ने की कोशिश करूंगा।

  1. संसाधन कुछ तरीकों से जुड़े हुए हैं - सभी संसाधनों का नक्शा एक (अन) निर्देशित ग्राफ बनाता है।
  2. प्रत्येक खिलाड़ी के पास कई संसाधन हो सकते हैं, प्रत्येक संसाधन एक खिलाड़ी के स्वामित्व में हो सकता है। खिलाड़ी अपने संसाधनों से अंक प्राप्त करने में सक्षम होना चाहिए। मैंने हस्ताक्षर के बारे में सोचा: fn addPoints(&mut self, allResources: &ResourcesMap) ->()
  3. खिलाड़ी किसी अन्य खिलाड़ी से अपने संसाधनों में से किसी एक संसाधन से जुड़ा संसाधन ले सकता है। इसके परिणामस्वरूप दूसरे खिलाड़ी के लिए कुछ अंक नुकसान हो सकते हैं।

समस्याएं:

  1. कैसे जंग (एक संभवतः चक्रीय संरचना, जहां प्रत्येक नोड कई नोड से की ओर इशारा किया जा सकता है) में इस तरह के ग्राफ का प्रतिनिधित्व करते हैं?
  2. मूल समस्या: अगर एक Player करने के लिए Resource अंक, मैं खिलाड़ी को संशोधित नहीं कर सकते हैं!

Resource रों Player इंगित क्योंकि - इस तरह के एक आपरेशन करने के लिए प्लेयर एक के कुछ संसाधनों से शुरू करने के लिए, खिलाड़ी बी के एक खिलाड़ी के बी संसाधन के लिए और कहा कि संसाधन से मानचित्र के माध्यम से ले जाने के घटाना होगा प्राकृतिक तरीके बिंदु। यह जंग में प्राकृतिक प्रतीत नहीं होता है (कम से कम मेरे लिए)।

उत्तर

6

cell documentation page के बजाय अच्छे उदाहरण हैं। जंग हमेशा आपको बुरी चीजों से बचाने की कोशिश करेगी (जैसे एक ही चीज़ के दो परिवर्तनीय संदर्भ)। इसके लिए यह जंग के अंतर्निर्मित संदर्भों के उपयोग के रूप में काफी "आसान" नहीं है, क्योंकि आपको रनटाइम-जांच करने की आवश्यकता है (जंग के संदर्भ संकलन समय पर चेक किए जाते हैं)।

RefCell प्रकार केवल इसके लिए मौजूद है। यह रनटाइम पर उत्परिवर्ती नियमों की जांच करता है। आपको कुछ मेमोरी और गणना-समय ओवरहेड मिलेगा, लेकिन आप उसी स्मृति-सुरक्षा के साथ समाप्त हो जाते हैं जो जंग इसके संकलन-समय जांच में वादा करता है।

आपका उदाहरण RefCell पर पोर्ट किया गया आपका उदाहरण निम्न जैसा दिखता है।

use std::cell::RefCell; 

struct Player { 
    points: i32, 
} 

// the lifetime is still needed to guarantee that Resources 
// don't outlive their player 
struct Resource<'a> { 
    owner: &'a RefCell<Player>, 
} 

impl<'a> Resource<'a> { 
    fn test(&self) -> i32 { 
     self.owner.borrow().points 
    } 
} 

fn main() { 
    let player = RefCell::new(Player { points: 0 }); 
    let mut resources = Vec::new(); 
    resources.push(Resource { owner: &player }); 
    player.borrow_mut().points = 30; 
    println!("{:?}", resources[0].test()); 
} 

मेरी चिंता का विषय है, अगर मैं क्या यह संकलन समय सुरक्षा का त्याग किए बिना एक जंग-तरीके से किया जा सकता है, ऐसा करने के लिए जंग में जावा कोड लिखने की कोशिश कर रहा है कोशिश कर रहा हूँ है? उस साझा म्यूटेबल स्थिति से बचें?

आप संकलन-समय-सुरक्षा का त्याग नहीं कर रहे हैं। जंग सुनिश्चित करता है (संकलन समय पर) कि आप अपने पुस्तकालयों का सही ढंग से उपयोग कर रहे हैं। फिर भी, यदि आप borrow* फ़ंक्शंस का उपयोग करते हैं, तो आपका प्रोग्राम पैनिक रनटाइम पर हो सकता है। यदि आप इसके बजाय try_borrow* फ़ंक्शंस का उपयोग करते हैं, तो आप जांच सकते हैं कि यह सफल हुआ है और यदि नहीं, तो कुछ फ़ॉलबैक ऑपरेशन करें।

आप अपने प्रकार (Rc<RefCell<Player>>) पर RefCell के संदर्भ संख्या वाले बॉक्स का भी उपयोग कर सकते हैं। फिर आपको केवल यह सुनिश्चित करने की आवश्यकता है कि आप चक्र नहीं बनाते हैं, या आपकी याददाश्त कभी मुक्त नहीं होगी। यह जावा की तरह अधिक होगा (हालांकि जावा स्वचालित रूप से चक्र पाता है)।

+0

अच्छा लगता है। मेरी चिंता यह है कि, यदि मैं जो करने की कोशिश कर रहा हूं वह जंग में जावा कोड लिखने की कोशिश कर रहा है, तो क्या यह संकलन समय सुरक्षा को बलि किए बिना जंग-मार्ग में किया जा सकता है? उस साझा म्यूटेबल स्थिति से बचें? –

+0

नोट: आप संकलन-समय-सुरक्षा का त्याग नहीं कर रहे हैं। जंग सुनिश्चित करता है (संकलन समय पर) कि आप अपने पुस्तकालयों का सही ढंग से उपयोग कर रहे हैं। फिर भी, यदि आप उधार * कार्यों का उपयोग करते हैं, तो आपका प्रोग्राम रनटाइम पर घबरा सकता है। यदि इसके बजाय आप try_borrow * फ़ंक्शंस का उपयोग करते हैं, तो आप जांच सकते हैं कि यह सफल हुआ है और यदि नहीं, तो कुछ फ़ॉलबैक ऑपरेशन करें। –

+1

आप संदर्भ प्रकार वाले बॉक्स (http://doc.rust-lang.org/std/rc/index.html) को अपने प्रकार के रेफसेल में भी उपयोग कर सकते हैं। फिर आपको केवल यह सुनिश्चित करने की आवश्यकता है कि आप चक्र नहीं बनाते हैं, या आपकी याददाश्त कभी मुक्त नहीं होगी। यह बहुत अधिक जावा होगा (हालांकि जावा स्वचालित रूप से चक्र पाता है) –

4

प्रत्येक संसाधन एक खिलाड़ी के स्वामित्व में जा सकता है।

प्रकार करते हैं कि तब बनाओ:

struct Player { 
    points: i32, 
    resources: Vec<Resource>, 
} 

struct Resource { 
    gold: i32, 
} 

fn main() { 
    let player1 = Player { 
     points: 30, 
     resources: vec![Resource { gold: 54 }], 
    }; 
    let player2 = Player { 
     points: 50, 
     resources: vec![Resource { gold: 99 }], 
    }; 

    // If you really need an array of all the resources... 
    // Although this seems like you should just ask the Player to do something 
    let mut resources: Vec<_> = vec![]; 
    resources.extend(player1.resources.iter()); 
    resources.extend(player2.resources.iter()); 
} 

संपादित धन्यवाद @ziggystar के लिए केवल एक Resource के लिए अपने मूल संस्करण की अनुमति दी खिलाड़ियों को ओर इशारा करते हुए के लिए। अब खिलाड़ियों के पास एन संसाधन हो सकते हैं, लेकिन वे अभी भी संसाधन का एकमात्र मालिक हैं।

+2

अब प्रत्येक खिलाड़ी के पास बिल्कुल एक संसाधन है। यह वही नहीं है। (प्रश्न नहीं पढ़ा) – ziggystar

+1

मैंने अपना प्रश्न संपादित किया, क्योंकि जिस तरह से मैंने इसे बताया, सही जवाब वह है जिसे आपने मुझे दिया था, लेकिन यह शायद मुझे जंग की समझ में आगे बढ़ता है। –

+0

संरचना का उदाहरण बनाने के कोड-शैली के संदर्भ में बेहतर तरीका क्या है: 'प्लेयर {'या' प्लेयर {' (व्हाइटस्पेस के साथ)? –

संबंधित मुद्दे