2015-05-24 7 views
7

मैं सिर्फ एक छोटे से जंग प्रोग्राम है जो फाइबोनैचि संख्या की गणना करता है और गणना memoizes लिखा है। यह काम करता है, लेकिन मैं थोड़ा उलझन में हूं क्यों, विशेष रूप से रिकर्सिव कॉल। (यह भी शायद मुहावरेदार नहीं है।)क्यों मैं स्पष्ट रूप से एक उधार, परिवर्तनशील चर उधार देने के लिए की जरूरत नहीं है?

यहां कार्यक्रम है:

use std::collections::HashMap; 

fn main() { 
    let n = 42; // hardcoded for simplicity 
    let mut cache = HashMap::new(); 
    let answer = fib(n, &mut cache); 
    println!("fib of {} is {}", n, answer); 
} 

fn fib(n: i32, cache: &mut HashMap<i32,i32>) -> i32 { 
    if cache.contains_key(&n) { 
     return cache[&n]; 
    } else { 
     if n < 1 { panic!("must be >= 1") } 

     let answer = if n == 1 { 
      0 
     } else if n == 2 { 
      1 
     } else { 
      fib(n - 1, cache) + fib(n - 2, cache) 
     }; 
     cache.insert(n, answer); 
     answer 
    } 
} 

यहाँ मैं कैसे समझ में क्या हो रहा है:

  • main में, let mut cache का अर्थ है "मैं सक्षम होना चाहते हैं इस हैशप को म्यूटेट करने के लिए (या चर को फिर से असाइन करें) "।
  • जब main कॉल fib, यह &mut cache गुजरता कहते हैं "मैं आप इस उधार कर रहा हूँ, और आप इसे उत्परिवर्तित करने की अनुमति दी रहे हैं।"
  • fib के हस्ताक्षर में, cache: &mut Hashmap का मतलब है "मैं एक परिवर्तनशील HashMap उधार होने की उम्मीद - उत्परिवर्तित करने के लिए अनुमति के साथ यह उधार लेने के लिए"

(कृपया मुझे ठीक कर लें मैं गलत हूँ।)

लेकिन fib रिकर्स करता है, fib(n -1, cache) पर कॉल करने के लिए, मुझे fib(n -1, &mut cache) का उपयोग करने की आवश्यकता नहीं है, और अगर मैं ऐसा करता हूं तो मुझे एक त्रुटि मिलती है: "अपरिवर्तनीय स्थानीय चर cache उत्परिवर्तनीय के रूप में उधार नहीं ले सकता"। है ना? यह एक अपरिवर्तनीय स्थानीय चर नहीं है, यह एक परिवर्तनीय उधार है - है ना?

error: mismatched types: 
expected `&mut std::collections::hash::map::HashMap<i32, i32>`, 
    found `&&mut std::collections::hash::map::HashMap<i32, i32>` 

कौन सा लगता है यह कह रही है "मैं एक परिवर्तनशील संदर्भ की उम्मीद है और एक परिवर्तनशील संदर्भ के लिए एक संदर्भ मिल गया":

अगर मैं fib(n - 1, &cache) कोशिश, मैं एक अलग त्रुटि मिलती है।

मुझे पता है कि fib रिकर्सिव कॉल में उधार दे रहा है क्योंकि अगर उसने स्वामित्व छोड़ दिया है, तो यह बाद में cache.insert पर कॉल नहीं कर सका। और मुझे पता है कि इस प्रत्यावर्तन के लिए एक विशेष मामला है, अगर मैं fib2 परिभाषित fib को लगभग समान हो सकता है, मैं उन्हें recurse एक दूसरे के माध्यम से हो सकता है और यह ठीक काम करता है क्योंकि नहीं है।

क्यों मैं स्पष्ट रूप से एक उधार, परिवर्तनशील चर उधार देने के लिए की जरूरत नहीं है?

+0

आप स्वामित्व पास कर सकते हैं, और फ़ंक्शन उत्तर और कैश के साथ एक टुपल लौटा सकता है: [PlayPen] (http://is.gd/tUadZ0) –

उत्तर

10
आपका तीन अंक

काफी स्पॉट पर हैं। जब संकलक आप &mut cache पारित करने के लिए अनुमति नहीं दी जाएगी, क्योंकि मूल्य वास्तव में पहले से ही लिया गया है है। cache का प्रकार &mut HashMap<i32, i32> है, इसलिए &mut cache गुजरने के परिणाम &mut &mut HashMap<i32, i32> के प्रकार में हैं। cache गुजरने के परिणामस्वरूप अपेक्षित प्रकार में परिणाम।

विशिष्ट त्रुटि संदेश cannot borrow immutable local variable cache as mutable ट्रिगर किया गया है क्योंकि परिवर्तनीय cache खुद को उत्परिवर्तनीय नहीं है, भले ही यह स्मृति इंगित करता है (HashMap) है। इसका कारण यह है तर्क घोषणा cache: &mut HashMap<i32, i32> एक mut चर घोषणा नहीं करता है। यह letlet mut से उत्परिवर्तन में भिन्नता के समान है। जंग जंगम तर्कों का समर्थन करता है, जो इस मामले में mut cache: &mut HashMap<i32, i32> जैसा दिखता है।

+0

हम्म। मुझे नहीं पता था कि मैं एक अपरिवर्तनीय चर में एक परिवर्तनीय मूल्य हो सकता है। क्या आपको यकीन है? 'म्यूट कैश =' दोनों को उत्परिवर्तनीय बनाता है - क्या संरचना को केवल परिवर्तनीय घोषित करने का कोई तरीका है? साथ ही, अगर मैं 'cache = और mut hashMap :: new();' fib' के शीर्ष पर जोड़ता हूं, तो मुझे आजीवन त्रुटि मिलती है, लेकिन "आप इस चर को फिर से असाइन नहीं कर सकते" त्रुटि नहीं। –

+0

इसके अलावा: दिलचस्प है कि "यह एक म्यूटेबल उधार है" एक प्रकार के माध्यम से चेक किया जाता है। मुझे समझने में मदद करने के लिए धन्यवाद। :) –

+0

@NathanLong आप वास्तव में एक अपरिवर्तनीय चर में एक mutable संदर्भ कर सकते हैं। ऐसा इसलिए है क्योंकि जंग को केवल अद्वितीय होने के लिए उत्परिवर्तनीय संदर्भ की आवश्यकता होती है: कोड का कोई अन्य भाग मूल्य को पढ़ने या संशोधित करने में सक्षम नहीं हो सकता है। यह सुनिश्चित करने के लिए संकलक के उधारकर्ता चेकर का हिस्सा है, कि सभी 'और म्यूट' अद्वितीय होने की गारंटी है (वही '' '' के लिए आवश्यक नहीं है)। चूंकि चर हमेशा अनूठे होते हैं (क्योंकि आप उनका स्वामित्व रखते हैं), एक अपरिवर्तनीय 'और mut' संदर्भ अभी भी अद्वितीय है, और इसलिए इसे संशोधित किया जा सकता है। आप [यह] (https://doc.rust-lang.org/book/references-and-borrowing.html) भी देखना चाहते हैं। :) – Snorre

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