Rust'a yeni gelen biri olarak benim anlayışım, açık yaşamların iki amaca hizmet ettiği.
Bir işleve açık bir ömür boyu ek açıklama koymak, o işlevin içinde görünebilecek kod türünü kısıtlar. Açık yaşam süreleri, derleyicinin programınızın istediğinizi yaptığından emin olmasını sağlar.
Siz (derleyici) bir kod parçasının geçerli olup olmadığını kontrol etmek istiyorsanız, siz (derleyici) çağrılan her işlevin tekrar tekrar bakmak zorunda kalmayacaksınız. Doğrudan bu kod parçası tarafından çağrılan işlev ek açıklamalarına bir göz atmak yeterlidir. Bu, programınızın sizin için (derleyici) akıl yürütmesini daha kolay hale getirir ve derleme sürelerini yönetilebilir hale getirir.
Nokta 1'de, Python ile yazılmış aşağıdaki programı düşünün:
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()
hangisi yazdıracak
array([[1, 0],
[0, 0]])
Bu tür davranışlar beni her zaman şaşırtıyor. Olan şey, df
hafızayı paylaşmaktır ar
, bu yüzden bazı df
değişikliklerin içeriğinde work
bu değişiklik de bulaşır ar
. Bununla birlikte, bazı durumlarda bu, bellek verimliliği nedenleriyle (kopya yok) tam olarak istediğiniz şey olabilir. Bu koddaki gerçek sorun, fonksiyonun second_row
ikinci yerine ilk satırı döndürmesidir; hata ayıklama iyi şanslar.
Bunun yerine Rust ile yazılmış benzer bir programı düşünün:
#[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);
}
Bunu derlerken,
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> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
Aslında iki hata alıyorsunuz, rolleri 'a
ve 'b
değişimleri olan bir tane var. Ek açıklamasına bakıldığında second_row
, çıktının &mut &'b mut [i32]
, yani çıktının ömür boyu referansa 'b
(ikinci satırın ömrü) bir referans olması gerektiğini buluyoruz Array
. Ancak, ilk satırı döndürdüğümüz için (ki bu da ömür boyu vardır 'a
), derleyici ömür boyu uyumsuzluktan yakınır. Doğru yerde. Doğru zamanda. Hata ayıklama bir esinti.