펄에서 서브 프로시저는 모든 전달된 매개변수가 자동으로 저장되는 특수 배열 변수 @_를 통해 인자를 받습니다. 펄의 특징은 매개변수가 @_에 참조로 들어간다는 점입니다. 따라서 함수 내에서 요소를 변경하면 외부에서도 해당 값이 변경됩니다.
예상치 못한 데이터 변경을 피하기 위해 매개변수를 변수에 복사하는 것이 좋습니다:
sub sum { my ($a, $b) = @_; return $a + $b; }
펄 함수는 항상 리스트 값을 반환하며, 함수의 결과는 마지막으로 계산된 리스트 또는 명시적인 return 문입니다.
sub minmax { my ($x, $y) = @_; return ($x < $y ? $x : $y, $x > $y ? $x : $y); } my ($min, $max) = minmax(4, 7); # $min = 4; $max = 7
스칼라 컨텍스트에서 함수를 호출하면 반환된 요소의 수가 반환됩니다.
많은 변수를 펄 함수에 전달할 때 원래 변수 값이 우연히 변경되지 않도록 하려면 어떻게 해야 하나요?
무의식적으로 대답합니다: "그냥 매개변수를 변수에 복사하면 됩니다!"
정답:
복사는 스칼라에 대해서만 작동합니다. 배열이나 해시를 사용하는 경우, 참조를 사용하여 데이터 전송을 명시적으로 관리하고 참조에 의한 복사를 피해야 합니다:
sub modify { my ($arr_ref) = @_; push @$arr_ref, 'new'; # 원래 배열을 변경함 } my @data = (1, 2, 3); modify(\@data); # 이제 @data = (1, 2, 3, 'new')
역사
이야기 1
대형 보고서 처리 스크립트에서 내부 함수가 주요 프로그램에서 전달된 배열 요소의 값을 변경했습니다. 결과적으로 함수 실행 후 원래 데이터가 왜곡되었습니다. 함수 작성자가 입력 값을 복사하지 않았기 때문에 발생한 오류로, 변경 사항이 로컬이 될 것이라고 잘못 추정한 것입니다 — 이는 배열과 함께 사용할 경우에는
@_에 대해 잘못된 것입니다.
이야기 2
Perl 4에서 스크립트를 마이그레이션하면서 변수를 다르게 복사했던 팀은 문제에 직면했습니다: 중첩 해시를 전달하면 서브 프로시저 호출 간 데이터가 예상치 않게 "유출"되었습니다. 한 함수에서 해시 필드를 수정하면 코드의 다른 부분에 영향을 미쳤습니다. 그 원인은
@_리스트의 해시에 대한 참조였습니다.
이야기 3
개발자는 결과 배열을 반환하는 함수를 구현했지만, 호출하는 곳에서 스칼라 컨텍스트를 사용했습니다:
$count = func(@params);. 첫 번째 반환 요소의 값이count변수에 할당될 것으로 예상했지만, 실제로는 리스트의 요소 수가$count에 할당되어 계산 지연과 혼란이 발생했습니다.