Perl에는 세 가지 주요 변수 선언 방법인 my, our, state가 있습니다.
sub example_state { state $counter = 0; $counter++; return $counter; } for (1..3) { print example_state(), " "; # 1, 2, 3을 순차적으로 출력합니다. }
올바른 사용 시기:
my — 전역 접근이 필요하지 않은 경우 변수에 대해 거의 항상 선호되는 선택입니다.our — 모듈 간에 변수를 내보내야 할 때, 공동 사용이 필요할 경우 사용합니다.state — 변수가 함수 호출 간에 값을 "기억"해야 하는 경우 사용할 수 있습니다 (예: 호출 카운터).our로 선언된 변수가 my와 마찬가지로 클로저에 캡처될 수 있을까요?
보통 사람들은 "네, 편리하지요"라고 대답하지만, 실제로 그렇지 않습니다. our 변수는 패키지에 대해 전역적이며, 클로저는 실제로 값을 생성할 때 변수를 바인딩하는 것이 아니라 전역 이름을 통해 접근합니다. 따라서 클로저 외부에서 "값"이 변경될 수 있으며, 이는 모든 클로저에 영향을 미칩니다!
our $x = 10; my $closure = sub { return $x; }; $x = 42; print $closure->(); # 10이 아니라 42를 반환합니다.
이야기
큰 로그 파싱 스크립트에서, 변수를 다양한 모듈의 함수에서 "편리하게 접근"하기 위해 our를 통해 선언했습니다. 그 결과, 한 함수에서 이 변수의 값이 변경되면서 다른 함수의 비정상적인 동작을 초래하여 로그의 병렬 처리를 방해했습니다.
이야기
함수 호출 간에 값을 저장해야 하는 변수에 대해 my를 사용하던 경우 (예: 재귀 순회 내의 카운터), 각 호출 시 값이 초기화되어 순회 로직에 오류를 일으켰습니다. state로 변경하자 문제가 해결되었습니다.
이야기
가져온 모듈에서 our을 잘못 사용한 결과 (변수를 Exporter를 통해 내보내지 않음), 동일한 변수 이름을 사용하는 두 개의 다른 모듈을 연결할 때 이름 충돌이 발생했습니다. 결과적으로 데이터가 한 컨텍스트에서 다른 컨텍스트로 "튕겨져" 나왔습니다.