문제

때를 통해서 읽 프로그래밍 Perl,제 2 판,51,페이지가 나를 혼동:

sub newopen {
    my $path = shift;
    local *FH;    #not my!
    open (FH, $path) || return undef;
    return *FH;
}

$fh = newopen('/etc/passwd');

내가 알고있는,왜 우리는 갱신되었을 사용하여 내?지금까지,나는 아무것도 볼 수 없는 것이 잘못 사용하는 경우 내().

감사합니다!

도움이 되었습니까?

해결책

의 진부한 대답입니다 당신이 사용하는 localmy *FH 구문 오류가 있습니다.

"오른쪽"(하지만 아주 깨달음)대답은 당신이 잘못하고있다.당신이 사용해야의 어휘는 c++컴파일러와 세 인수의 양식 open 대신 합니다.

sub newopen {
    my $path = shift;
    my $fh;
    open($fh, '<', $path) or do {
        warn "Can't read file '$path' [$!]\n";
        return;
    }
    return $fh;
}

정말 답변 필요한의 설명 사이의 차이는 어휘와 전역 변수 사이에 변수의 범위와 기간.

변수의 범위는 프로그램의 일부는 그것의 이름은 유효합니다.범위는 정적을 제공합니다.변수의 기간에,다른 한편으로는,동적을 제공합니다.편은 시간 동안 프로그램을 실행하는 변수가 존재하고는 가치를 가지고.

my 선 어휘 변수입니다.어휘 변수가 범위의 관점에서는 선언을 끝의 바깥쪽 구획(혹은 파일)할 수 있습이 다른 변수를 동일한 이름으로 다른 범위에서이없는 충돌이 있습니다.(할 수도 있습니다 다시 사용하기에 이름이 겹치는 범위를,그러나 그렇게 하지 않습니다.) 의 시간을 어휘 변수를 관리하는 터치 참조한다.그래서 거기에 적어도 하나를 참조하여 변수 값이 존재하는 경우에도 이름을 올바르지 않습 특정 범위 내! my 또한 런타임을 효과-그것을 할당 변수로 주어진 이름입니다.

local 조금 다릅니다.그것은에서 작동하는 글로벌 변수입니다.글로벌 변수에는 전역 범위(이름이 유효한 곳에)및 시간의 인생 전체의 프로그램입니다.What local 하지 않는 임시로 변경 의 글로벌 변수입니다.이는 때때로"동적 범위 지정합니다." 이 변화의 시작 시점에서의 local 을 선언하고 지속가 끝날 때까지의 바깥쪽 구획된 후 오래 된 가치가 복원됩니다.그것의 중요한 새로운 값이 제한되지 않는 블록-그것은 어디서나 볼 수 있(을 포함한 서브 루틴이라고).계산 규칙 참조직에 적용,그래서 당신은 당신이 걸릴 수 있고 참조를 유지하는 지역화된 값이 변경 후에 만료되었습니다.

다시 예제: *FH 글로벌 변수입니다.더 정확하게 그것은"typeglob"--컨테이너에 대한 집합의 글로벌 변수입니다.A typeglob 슬롯을 포함한 각각의 기본 변수의 유형(스칼라,배열,해시)여러 다른 것들입니다.역사적으로 사용되는 펄 typeglobs 저장하기 위한 c++컴파일러와 local-izing 그하는 데 큰 도움이 되었습니다 그들은 먹지 않았다.어휘 변수가 있지 않 typeglobs 는 이유는 말 my *FH 구문 오류가 있습니다.

에 현대적인 버전의 펄 어휘할 수 있는 변수 및으로 사용되어야 하는 c++컴파일러 대신 합니다.과는 우리를 다시 제공"바"대답합니다.

다른 팁

샘플 코드에서 내장 서브 루틴에 대한 호출 open 베어 단어를 파일 핸들로 사용하는데, 이는 전역 변수와 동일합니다. 처럼 Nathan Fellman의 대답 설명, 사용 local 동일한 이름을 가진 다른 글로벌 변수가 스크립트 또는 모듈의 다른 곳에 정의되는 경우이 맨 단어를 현재 코드 블록에 로컬로 현지화합니다. 이렇게하면 이전에 정의 된 글로벌 변수가 새로운 선언에 의해 사라지는 것을 방지합니다.

이것은 오래된 Perl 시절에 매우 일반적인 관행 이었지만 Perl 5.6 기준으로 스칼라를 사용하는 것이 훨씬 낫습니다 ( my 파일 핸들을 정의하기 위해 귀하의 질문에서 힌트를 힌트 한 선언) 또한 세 가지 인수 호출을 사용하십시오. open.

use Carp;
open my $error_log, '>>', 'error.log' or croak "Can't open error.log: $OS_ERROR";

제쳐두고 표준 입력/출력 읽기 및 쓰기의 경우 두 인수를 사용하는 것이 여전히 좋습니다. open:

use Carp;
open my $stdin, '<-' or croak "Can't open stdin: $OS_ERROR";

또는 사용할 수 있습니다 IO::File 클래스에 파일 핸들을 축복하는 모듈 :

use IO::File;
my $error_log = IO::File->new('error.log', '>>') or croak "Can't open error.log: $OS_ERROR");

여기서 크레딧의 대부분은 간다 Damian Conway, 훌륭한 책 Perl 모범 사례의 저자. Perl 개발에 대해 진지하다면이 책을 구매해야합니다.

왜 오래된 책을 읽고 있습니까? 제 3 판은 오랫동안 나왔습니다! 어떤 버전의 Perl을 사용하고 있습니까? 제 2 판은 PERL 5.004 (5.4.x) 또는 그에 대한 방향을 설명합니다.

요즘에는 파일 핸들에 TypeGlob 표기법을 사용해서는 안됩니다. '어휘 파일 핸들'을 사용하십시오 (참조 열려 있는, 나는 생각합니다) 또는 파일 핸들 대신 모듈 또는 친척 중 한 명.


Michael Schwern과 Ysth에게 의견을 보내 주셔서 감사합니다.

나는 그것이 때문이라고 믿는다 my 스택에 변수의 새 사본을 할당하고 블록을 종료 할 때 손실됩니다. local 기존을 저장합니다 *FH 다른 곳에서 그리고 기존을 무시합니다 *FH. 스택을 종료 할 때 오래된 것을 복원합니다. 와 함께 my 그만큼 *FH TypeGlob은 블록을 종료 할 때 범위를 벗어납니다. 와 함께 local 기존이 계속 유지되므로 반품 후에도 계속 사용할 수 있습니다.

나는 이것을 100% 확신하지는 않지만 아마도 당신을 올바른 방향으로 가리킬 수 있습니다.

현지화 된 파일 핸들을 참조하십시오 여기, 나는 그것이 설명한다고 생각합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top