2015-07-13 4 views
7

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

मैं क्या कर रहा हूँ मूल रूप से है इस - मैं एक struct कि एक सूची का आयोजन करेगा निर्धारित करें:

struct ListNode<T> { 
    val: T, 
    tail: List<T> 
} 

struct List<T>(Option<Box<ListNode<T>>>); 

खाली सूची बस List(None) का प्रतिनिधित्व करती है। ,

impl<T> List<T> { 
    fn append(self, val: T) -> List<T> { 
     match self { 
      List(None) => List(Some(Box::new(ListNode { val: val, tail: List(None) }))), 
      List(Some(node)) => List(Some(Box::new(ListNode { val: node.val, tail: node.tail.append(val) }))) 
     } 
    } 
} 

ठीक है, ताकि एक त्रुटि के साथ विफल:

अब, मैं एक सूची में जोड़ने के लिए सक्षम होना चाहते हैं: एक व्याख्या है कि यह साथ node.tail पर "चले गए मूल्य का इस्तेमाल किया नोड" "node.val" पर चले गए। यह समझ में आता है।

तो, मैं तरीके एक struct के एक से अधिक क्षेत्र का उपयोग करने के लिए देखते हैं और मैं इस लगता है: Avoiding partially moved values error when consuming a struct with multiple fields

बढ़िया है, इसलिए मुझे लगता है कि यह करेंगे:

List(Some(node)) => { 
    let ListNode { val: nval, tail: ntail } = *node; 
    List(Some(Box::new(ListNode { val: nval, tail: ntail.append(val) }))) 
} 

ठीक है, नहीं, अभी भी नोड असाइनमेंट पर स्थानांतरित किया जा रहा है ("त्रुटि:" पूंछ मूल्य "नोड" का उपयोग "पूंछ: ntail" पर)। जाहिर है यह अब लिंक में काम नहीं करता है।

मैं भी refs का उपयोग कर की कोशिश की है:

List(Some(node)) => { 
    let ListNode { val: ref nval, tail: ref ntail } = *node; 
    List(Some(Box::new(ListNode { val: *nval, tail: (*ntail).append(val) }))) 
} 

इस बार विखंडन से गुजरता है, लेकिन नए नोड के निर्माण के साथ विफल रहता है "त्रुटि: उधार ली गई सामग्री से बाहर स्थानांतरित नहीं कर सकते"।

क्या मुझे यहां कुछ स्पष्ट याद आ रही है? यदि नहीं, तो संदर्भ द्वारा पारित नहीं किए गए संरचना के एकाधिक फ़ील्ड तक पहुंचने का उचित तरीका क्या है?

किसी भी मदद के लिए अग्रिम धन्यवाद!

संपादित करें: ओह, मुझे शायद यह जोड़ना चाहिए कि मैं जंग 1.1 स्थिर का उपयोग कर रहा हूं।

उत्तर

5

Box पर कुछ अजीब बातचीत है। आपको एक इंटरमीडिएट लेट स्टेटमेंट जोड़ने की ज़रूरत है जो बॉक्स को अनचाहे करता है।

List(Some(node)) => { 
    let node = *node; // this moves the value from the heap to the stack 
    let ListNode { val, tail } = node; // now this works as it should 
    List(Some(Box::new(ListNode { val: val, tail: tail.append(value) }))) 
} 

ध्यान दें कि मैं value करने के लिए अपने समारोह तर्क का नाम बदला, तो मैं नाम बदलने के बिना संक्षिप्त रूप में destructuring लिख सकते हैं।

Try it out in the playground.

+0

धन्यवाद! यह वास्तव में काम करता है :) बॉक्स क्यों काम करेगा, यद्यपि? क्या कोई उचित स्पष्टीकरण है? – ebvalaim

+0

मुझे पूरा यकीन है कि इसे इस तथ्य से करना है कि अनबॉक्सिंग डेफ कुछ कंपाइलर जादू है। –

+1

यहां संबंधित बग है: https://github.com/rust-lang/rust/issues/16223 –

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

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