2008-10-14 4 views
24

나는 효과적으로 몇 가지 코드에 다른 장소의 무리에 다음에서 기록 일부 자동 생성 된 코드가 있습니다다른 스택 프레임에서 펄 변수를 어떻게 현지화 할 수 있습니까?

no warnings 'uninitialized'; 
local %ENV = %ENV; 
local $/ = $/; 
local @INC = @INC; 
local %INC = %INC; 
local $_ = $_; 
local $| = $|; 
local %SIG = %SIG; 
use warnings 'uninitialized'; 

때 자동 생성 코드, 일부는 코드가 "하는 것이 반드시 필요한 것은 아니라고 주장 아름답다. "그러나 나는 이것을 서브 루틴으로 끌어 들이고 싶다. 그러나 그 서브 루틴에서 변수를 지역화합니다. 호출 스택 프레임에서 이러한 변수를 지역화하는 방법이 있습니까?

업데이트 : 비슷한 맥락에서 더 높은 스택 프레임에서 eval을 실행할 수 있으면 좋을 것입니다. 나는 파이썬이 이미 이것을 가지고 있다고 생각한다. Perl도 그렇게한다면 좋을 것입니다.

+0

파이썬에서 본 것이 확실합니까? Tcl의'uplevel'이 떠오른다. 그러나 헥센의 대답은 어쨌든 훨씬 낫다. – cfi

답변

30

아마도 해당 지역 사용자를 사용하는 코드를 클로저로 생성하도록 준비 할 수 있습니까? 그럼 당신은

sub run_with_env { 
    my ($sub, @args) = @_; 
    no warnings 'uninitialized'; 
    local %ENV = %ENV; 
    local $/ = $/; 
    local @INC = @INC; 
    local %INC = %INC; 
    local $_ = $_; 
    local $| = $|; 
    local %SIG = %SIG; 
    use warnings 'uninitialized'; 
    $sub->(@args); 
} 

run_with_env(sub { 
    # do stuff here 
}); 

run_with_env(sub { 
    # do different stuff here 
}); 
+2

D' oh! 회고록에서 당황 스러울 정도로 분명합니다. 코드를 자동 생성하므로이 작업은 간단합니다. – Ovid

+0

그건 멋진 아이디어, 그 같은 문제를 반전! –

+0

정말 % main ::을 현지화하려는 것 같습니다. 그렇게 할 수있는 방법이 있는지 궁금합니다. –

3

저는 Perl에 익숙하지 않습니다. 실제로 가능하다면 용서하십시오. 그러나 일반적으로 스택 프레임의 로컬 변수는 해당 스택 프레임 내에서만 사용할 수 있습니다. 상위 또는 하위 중 하나에서 액세스 할 수 없습니다 (해시 포인터 산술을하지 않으면 성공할 수는 없습니다). 변수 선언의 큰 블록은 불행하게도 당신이 살아야 할 무언가입니다.

QuantumPete

+1

이 변수는 내장 된 전역 변수이다. 그것들은 잘 알려져 있고 정의되어있는 것처럼 전역 적인지 적 오버 헤드를 가지고 있지 않습니다. 안타깝게도 전역 변수는 여전히 전역 효과를 가지며 지역화는 현재 범위의 변경을 제한합니다. – Ovid

+2

또한 로컬에는 사용자가 생각하고있는 동작이 아니라 정확하지 않습니다. local을 사용하면 지역화 된 변수에 액세스하고, 수정하고, 업데이트하고, 변경하고, 해당 호출 스택에서 새로운/수정 된 값으로 지역화 된 클로저를 벗어날 때까지 계속할 수 있습니다. –

1

TCL에서는 uplevel를 사용할 수 있습니다. Perl에 관해서는, 나는 모른다.

+3

나는 궁금해합니다. TCL 키워드에 대한 Wikipedia 항목이있는 이유는 무엇입니까?지금 포장을 풀기 위해 하나를 추가해야합니까? :) – Ovid

+0

[Sub :: Uplevel] (http://search.cpan.org/perldoc?Sub=:Upuravel)과 같은 것? 그것이 그것이 무엇을위한 것입니까? – bart

+0

Sub :: Uplevel이 모두 도움이된다고 생각하지 않습니다. "발신자"는 네임 스페이스가 아닙니다. –

6

QuantumPete가 downvoted되는 이유를 잘 모르겠다. local에 호출 블록의 변수를 초기화하도록 알릴 수 없습니다. 그 기능은 특별하고, 초기화/해체는 실행 된 블록에서만 작동합니다.

같은 Sub::Uplevel하고 서브 루틴에 대한 caller()를 "바보"또는 (각각) 높은 스택 프레임 값의 '멀리뛰기 수익을'할 시도 할 수 Devel::RunBlock 같은 일부 실험 모듈이 있습니다

, 그러나이 중 어느 것도 아무것도 할 local이 변수를 처리하는 방법에 영향을 미칩니다. (시도했습니다 :)

이제는 필요로하는 범위에서 로컬 선언을 사용하여 살아야 할 것처럼 보입니다.

3

perldoc을의 perlguts를 말한다 수 :

The "Alias" module implements localization of the basic types within 
    the caller's scope. People who are interested in how to localize 
    things in the containing scope should take a look there too. 

FWIW. 나는 앨리어스를 자세히 보지 않았습니다. 얼마나 쉬운지를 알기에 충분합니다.