Rustの初心者として、私の理解では、明示的なライフタイムには2つの目的があります。
関数に明示的なライフタイムアノテーションを付けると、その関数内に表示される可能性のあるコードのタイプが制限されます。明示的な存続時間により、コンパイラーはプログラムが意図したとおりに動作していることを確認できます。
あなた(コンパイラー)がコードの一部が有効かどうかをチェックしたい場合、あなた(コンパイラー)は呼び出されたすべての関数の内部を繰り返し調べる必要はありません。そのコードから直接呼び出される関数のアノテーションを確認するだけで十分です。これにより、プログラム(コンパイラ)の推論がはるかに容易になり、コンパイル時間を管理しやすくなります。
ポイント1.で、Pythonで作成された次のプログラムを考えてみます。
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
が2番目ではなく最初の行を返すことです。それをデバッグする幸運。
代わりに、Rustで作成された同様のプログラムを検討してください。
#[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> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
実際には、あなたが2つのエラーを取得し、そこの役割を持つものもある'a
と'b
入れ替えます。の注釈を見るsecond_row
と、出力はであることがわかります&mut &'b mut [i32]
。つまり、出力は'b
、有効期間(の2行目の有効期間)を持つ参照への参照であるはずArray
です。ただし、最初の行(ライフタイムがある'a
)を返すため、コンパイラーはライフタイムの不一致について不平を言います。適切な場所で。正確な時に。デバッグは簡単です。