Rust의 새로운 이민자로서, 나의 이해는 명백한 수명이 두 가지 목적에 기여한다는 것입니다.
함수에 명시적인 수명 주석을 넣으면 해당 함수 안에 나타날 수있는 코드 유형이 제한됩니다. 컴파일러는 명시 적 수명을 통해 프로그램이 의도 한대로 작동하는지 확인할 수 있습니다.
(컴파일러)가 코드 조각이 유효한지 확인하기를 원한다면, (컴파일러)는 호출 된 모든 함수를 반복해서 살펴볼 필요는 없습니다. 해당 코드에서 직접 호출하는 함수의 주석을 살펴 보는 것으로 충분합니다. 이렇게하면 프로그램 (귀하의 컴파일러)이 훨씬 쉽게 추론하고 컴파일 시간을 관리 할 수 있습니다.
포인트 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
가 두 번째 행 대신 첫 번째 행을 반환한다는 것입니다. 행운을 빌어 디버깅.
대신 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> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
실제로 두 가지 오류가 발생하며 역할 'a
과 'b
교환 이있는 오류도 있습니다. 의 주석을 보면 second_row
출력이이어야한다는 것을 알 수 있습니다 &mut &'b mut [i32]
. 즉, 출력은 수명이있는 참조 'b
(두 번째 행의 수명)에 대한 참조 여야합니다 Array
. 그러나 첫 번째 행 (lifetime 'a
) 을 반환하기 때문에 컴파일러는 수명 불일치에 대해 불평합니다. 올바른 장소에서. 적시에. 디버깅은 산들 바람입니다.