2010-08-21 4 views
7

지도를 이해할 수 있다고 생각했지만 다음은 내가 이해하지 못하는 결과가 있습니다. 왜 그런 일이 벌어지는 지 알 수 없습니다.

$__do_stuff_to_file 호출 중에 재설정되므로 문제가있는 것입니다. 그래서 인쇄 될 내용은 일 때 here: \nhere:\n입니다.

참고 : 이것은 테스트 코드가 아닙니다. 그것은 내가 실험실에서 본 기억이 있습니다. @array의 내용이 왜 변경됩니까?

_some_func에서 1을 반환하기 전에 $_$f으로 설정 한 경우 그런 다음 배열은 여전히 ​​손상되지 않습니다. 펄

my @array = ("donkie", "kong"); 
map { push @junk, _some_func('blah', $_); } @array; 

if (join ('', @junk) !~ /0/) 
{ # for example sake this is always true since return 1 from _some_func. 
    print map { "here: $_\n"; } @array; 
} 

sub _some_func 
{ # for example sake, lets say $f always exists as a file. 
    my $j = shift; 
    my $f = shift; 
    return 0 if !open(FILE, "< $f"); 
    close FILE; 
    _do_stuff_to_file($f); 

    return 1; 
} 


sub _do_stuff_to_file 
{ 
    my $f = shift; 
    open(IN, "< $f"); 
    open(OUT, "> $f.new"); 

    while (<IN>) 
    { 
     print OUT; 
    } 

    close IN; 
    close OUT; 
} 
+3

질문에 이미 답변이 포함되어 있습니다. 질문을 "$ _"하는 것을 피하는 방법은 무엇입니까? 우리가 대답 할 수있는 것이기 때문에 (그리고 Michael Carman은 이미 가지고 있습니다.) – hobbs

+0

나는 hobbs에게 질문 제목을 추천했습니다. @ 어제 당신은 그것을 변경합니까? – dolmen

답변

9

많은 기능은 기본 변수 $_를 사용 : 여기

내가보고있는 무슨 설명하는 예제 프로그램입니다. 그 중에는 map 및 readline 연산자 <>이 있습니다. foreach처럼 map은 처리하는 목록의 각 요소에 대한 별칭을 루프 변수로 만듭니다. 무엇 일어나는 것은이 줄 것입니다 다음 map의 앨리어싱이 적용되는 동안
while (<IN>) 

$_에 할당된다. 이것은 $_ (또는 다른 전역 변수)을 사용하는 데있어서의 문제 중 하나입니다 - 멀리서 이상한 행동을하십시오. 당신이 $_을 사용하려고하는 경우, 먼저 지역화 :

local $_; 
while (<IN>) 
... 

또는, 대신 어휘 변수 사용 : _ 초기 배열을 변경됩니다 $을 수정

while (my $line = <IN>) 
+0

하지만 $ _을 사용하면 배열의 내용이 변경되는 이유는 무엇입니까? isnt $ _ 배열의 현재 값을 복사하는 변수입니까? – user318747

+0

괜찮습니다. 감사합니다. – user318747

4

를, $이 _ 별칭이기 때문에 현재 요소로. 코드는 다음과 같아야합니다.

my @array = ("donkie", "kong"); 
my @junk=map {_some_func('blah', $_) } @array; 

if (join ('', @junk) !~ /0/) 
{ # for example sake this is always true since return 1 from _some_func. 
    print map { "here: $_\n"; } @array; 
} 

sub _some_func 
{ # for example sake, lets say $f always exists as a file. 
    my $j = shift; 
    my $f = shift; 
    return 0 if !-e $f; 
    _do_stuff_to_file($f); 
    return 1; 
} 


sub _do_stuff_to_file 
{ 
    my $f = shift; 
    local $_; 
    open(IN, "<",$f); 
    open(OUT, ">", "$f.new"); 

    while (<IN>) 
    { 
     print OUT; 
    } 

    close IN; 
    close OUT; 
} 

P.S. map은 동일한 수의 요소를 가진 배열을 반환합니다 (스칼라가 블록에서 반환 된 경우). grep은 블록이 true 인 요소 만 반환합니다.

+1

'map'리스트가 반환됩니다. '@doubled = map {$ _, $ _} (1 .. 5)' –

0

알렉산더와 마이클의 대답을 승인합니다. _do_stuff_to_file()$_의 값을 변경합니다. map의 문맥에서와 같이 $_은 매핑 된 요소의 저장소 이름 일 뿐이므로 배열이 변경됩니다.

Alexander와 Michael은 _do_stuff_to_file()을 변경하여 $_ 값에 영향을 미치지 않도록 제안합니다. 외부 범위를 혼란시키지 않으려면 $_과 같은 특수 변수를 지역화하는 것이 좋습니다.일반적인 스타일

map { my $x=$_; local $_; push @junk, _some_func('blah', $x); } @array; 

이상 다음 :

을 함수를 호출하기 전에 "휴식"로컬 델링으로 맵 블록 내부 링크 : 여기

그 기능을 만지지 않도록 대안 솔루션입니다
@junk = map { my $x=$_; local $_; _some_func('blah', $x) } @array; 
+0

또는 맵을 사용하기 전에'my $ _; '와 같은 수의 요소를 입력 할 필요는 없습니다. 전역 변수가 아닌 어휘 $ _ – ysth

+0

@ysth "my $ _"는 새로운 변수를 맵 블록에 생성하지만 _some_func() 및 _do_stuff_to_file() 컨텍스트에는 영향을 미치지 않으므로 이렇게하지 않습니다. 문제를 해결하십시오. – dolmen

+0

예, @ * map의 문제를 수정합니다. @array의 별칭 값을 변경할 수 없으면 예외가됩니다. – ysth

4

$ _을 (를) 설정 한 대부분의 항목은 암시 적으로 별칭이므로이 문제가 발생하지 않습니다. 예외는 while (<filehandle>)입니다. $ _ (이상적으로는 my $_;)를 현지화 할 수 있지만, 암시 적으로 $ _를 설정하는 동안은 절대 사용하지 않는 것이 좋습니다. 대신 while (my $line = <filehandle>)하십시오. (특수 암시 적 정의()도 여전히 발생합니다.)

관련 문제