रस्ट के एक नवागंतुक के रूप में, मेरी समझ यह है कि स्पष्ट जीवनकाल दो उद्देश्यों की सेवा करता है।
किसी फ़ंक्शन पर एक स्पष्ट जीवनकाल एनोटेशन डालना कोड के प्रकार को प्रतिबंधित करता है जो उस फ़ंक्शन के अंदर दिखाई दे सकता है। स्पष्ट जीवनकाल संकलक को यह सुनिश्चित करने की अनुमति देता है कि आपका कार्यक्रम वही कर रहा है जो आपने इरादा किया था।
यदि आप (संकलक) चाहते हैं कि कोड का एक टुकड़ा वैध है या नहीं, तो आप (संकलक) को यह कहा जाता है कि वह प्रत्येक फ़ंक्शन के अंदर दिखना नहीं चाहता। यह उन कार्यों के एनोटेशन पर एक नज़र रखने के लिए पर्याप्त है जो सीधे उस कोड के कोड द्वारा कहे जाते हैं। यह आपके कार्यक्रम को आपके (कंपाइलर) के बारे में तर्क करने में बहुत आसान बनाता है, और संकलन समय को प्रबंधनीय बनाता है।
बिंदु 1 पर, पायथन में लिखे गए निम्नलिखित कार्यक्रम पर विचार करें:
import pandas as pd
import numpy as np
def second_row(ar):
return ar[0]
def work(second):
df = pd.DataFrame(data=second)
df.loc[0, 0] = 1
def main():
# .. load data ..
ar = np.array([[0, 0], [0, 0]])
# .. do some work on second row ..
second = second_row(ar)
work(second)
# .. much later ..
print(repr(ar))
if __name__=="__main__":
main()
जो छपेगा
array([[1, 0],
[0, 0]])
इस प्रकार का व्यवहार मुझे हमेशा आश्चर्यचकित करता है। क्या हो रहा है कि df
स्मृति के साथ साझा किया जा रहा है ar
, इसलिए जब कुछ सामग्री में df
परिवर्तन होता है work
, तो यह परिवर्तन के ar
रूप में भी संक्रमित होता है । हालाँकि, कुछ मामलों में यह वही हो सकता है जो आप चाहते हैं, स्मृति दक्षता कारणों (कोई प्रतिलिपि नहीं) के लिए। इस कोड में असली समस्या यह है कि फ़ंक्शनsecond_row
दूसरी के बजाय पहली पंक्ति में लौट रहा है; सौभाग्य कि डिबगिंग।
रस्ट में लिखे एक समान कार्यक्रम के बजाय विचार करें:
#[derive(Debug)]
struct Array<'a, 'b>(&'a mut [i32], &'b mut [i32]);
impl<'a, 'b> Array<'a, 'b> {
fn second_row(&mut self) -> &mut &'b mut [i32] {
&mut self.0
}
}
fn work(second: &mut [i32]) {
second[0] = 1;
}
fn main() {
// .. load data ..
let ar1 = &mut [0, 0][..];
let ar2 = &mut [0, 0][..];
let mut ar = Array(ar1, ar2);
// .. do some work on second row ..
{
let second = ar.second_row();
work(second);
}
// .. much later ..
println!("{:?}", ar);
}
यह संकलन, आपको मिलता है
error[E0308]: mismatched types
--> src/main.rs:6:13
|
6 | &mut self.0
| ^^^^^^^^^^^ lifetime mismatch
|
= note: expected type `&mut &'b mut [i32]`
found type `&mut &'a mut [i32]`
note: the lifetime 'b as defined on the impl at 4:5...
--> src/main.rs:4:5
|
4 | impl<'a, 'b> Array<'a, 'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 4:5
--> src/main.rs:4:5
|
4 | impl<'a, 'b> Array<'a, 'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
वास्तव में आपको दो त्रुटियां मिलती हैं, एक की भूमिका भी होती है 'a
और 'b
आपस में जुड़ी हुई। के एनोटेशन को देखते हुए second_row
, हम पाते हैं कि आउटपुट होना चाहिए &mut &'b mut [i32]
, अर्थात, आउटपुट को जीवनकाल 'b
(दूसरी पंक्ति के जीवनकाल ) के संदर्भ के संदर्भ में माना जाता है Array
। हालांकि, क्योंकि हम पहली पंक्ति (जिसमें जीवनकाल है 'a
) वापस कर रहे हैं , संकलक जीवन भर बेमेल के बारे में शिकायत करता है। सही जगह पर। सही समय पर। डिबगिंग एक हवा है।