0

나는 perl이 서브 루틴을 실행할 때 call-by-reference를 사용한다는 것을 읽었다. 나는이 속성을 확인하는 간단한 코드를 만들었지 만, 펄이 경우처럼 통화 값에 의한 동작 :perl이 call-by-reference 인 경우 왜 이런 일이 발생합니까?

$ perl example.pl 
x1:70 y1:50 
x:50 y:70 

인수가 처리 된 경우 :

$x=50; 
$y=70; 

sub interchange { 
    ($x1, $y1) = @_; 

    $z1 = $x1; 
    $x1 = $y1; 
    $y1 = $z1; 

    print "x1:$x1 y1:$y1\n"; 
} 

&interchange ($x, $y); 

print "x:$x y:$y\n"; 

이 다음과 같은 출력을 생성을 참조에 의한 호출, x가 x1과 같고 y가 y1과 같지 않아야합니까?

+2

[경고] (http://perldoc.perl.org/warnings.html), [어휘 범위 변수] (http://perldoc.perl.org/perlsub.html#Private-Variables-via-my())에 익숙하고,'&'가 붙은 서브 루틴을 호출하지 않는다면 [당신이 왜 이것을하고 그렇게 할 필요가 있는지 알고 있습니다] (http://perldoc.perl.org/perlsub.html#Prototypes). 더 일찍할수록 더 행복해집니다. :) – pilcrow

+0

또한 [값을 바꿀 수있는 더 쉬운 방법]이 있습니다 (http://stackoverflow.com/a/18606254/132382). – pilcrow

답변

3

하위 외부 값을 수정하려면 @_ 값을 수정해야합니다.

이 값을 수정 않습니다 sub interchange다음이 출력을 제공

sub interchange { 
    ($x1, $y1) = @_; # this line copies the values to 2 new variables 

    $z1 = $x1; 
    $x1 = $y1; 
    $y1 = $z1; 

    $_[0] = $x1; # this line added to change value outside sub 
    $_[1] = $y1; # this line added to change value outside sub 

    print "x1:$x1 y1:$y1\n"; 
} 

을 :

x1:70 y1:50 
x:70 y:50 
여기

더 많은 정보 : http://www.cs.cf.ac.uk/Dave/PERL/node51.html

그러나, 문서를 인용 :

이 함수가 주 프로그램의 @array 변수에 영향을 줄 수 있음을 알 수 있습니다. 일반적으로 이것은 프로그램의 나머지 부분에서 함수가 수행하는 작업을 격리하지 않기 때문에 나쁜 프로그래밍 방법으로 간주됩니다.

+3

'sub interchange {@_ [0,1] = @_ [1,0]} ' – Borodin

+1

@ 보 로딘 OP의 원래 코드를 거의 바꾸려고합니다. 그러나 멋지고 간결한 코드 :) – AntonH

8

Perl은 항상 참조 용입니다. 당신은 성명 ($x1, $y1) = @_입니다 원본 인수 값을 복사, @ 원래 매개 변수 별칭을 보유하고 있기 때문에. perlsub 맨 페이지에서

: 배열 @_에서 쇼까지 전달

모든 인수입니다. 따라서 두 개의 인수가있는 함수를 호출하면 $ [0] 및 $ [1]에 저장됩니다. @_ 배열은 로컬 배열이지만 그 요소는 실제 스칼라 매개 변수의 별칭입니다. 특히 $ _ [0] 요소가 업데이트되면 해당 인수가 업데이트됩니다 (업데이트 할 수없는 경우 오류가 발생 함).

+2

+1 지금까지 가장 정확하고 가장 정확한 답. – pilcrow

-2

저는 Perl도 시작 했으므로, 여러분이 서브 루틴으로 전달하는 것만 오해하고 있다고 생각합니다. $ x와 $ y를 전달하면 스칼라 $ x와 $ y가 전달됩니다. 명시 적으로 참조를 전달해야하며 스칼라 일 수도 있습니다 (단 하나만 서브 루틴으로 전달할 수 있습니다). 배열과 해시에 대한 참조가 이후 참조로 전달되어야하므로 호출 기반 참조가 어디에서 왔는지 이해합니다.

이 코드는 당신이 찾고있는 무엇을 수행해야합니다

#!/usr/bin/perl 

$x=50; 
$y=70; 

sub interchange { 
    ($x1, $y1) = @_; 

    $z1 = $$x1; # Dereferencing $x1 
    $$x1 = $$y1; # Dereferencing $x1 and $y1 
    $$y1 = $z1; # Dereferencing $y1 

    print "x1:$$x1 y1:$$y1\n"; 
} 

&interchange (\$x, \$y); # Passing references to $x and $y, not their values 

print "x:$x y:$y\n"; 

나는 $ \의 $ x와 \의 $ y를을 사용하여 x와 $ y를 참조 전달합니다. 그런 다음 $$ x와 $$ y를 사용하여 서브 루틴 내에서 참조를 취소합니다.

관련 문제