2008-10-14 13 views
24

ben etkili bazı kodda farklı yerlerde bir demet aşağıdaki dışarı yazıyor bazı otomatik oluşturulan kod var:Perl değişkenlerini farklı bir yığın çerçevesinde nasıl yerelleştirebilirim?

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

zaman otomatik olarak oluşturma kodu, bazıları kod "olması kesinlikle gerekli olmadığını iddia güzel "ama bunu bir altprograma çekmek istiyorum. Ancak, bu değişkenler o alt yordamda yerelleştirilir. Çağıran yığın çerçevesinde bu değişkenleri yerelleştirmenin bir yolu var mı?

Güncelleştirmesi: Benzer şekilde, daha yüksek bir yığın çerçevesinde değerlendirmeyi yürütmek güzel olurdu. Bence Python zaten buna sahip. Perl'nin de yapması güzel olurdu.

+0

Bunu Python'da gördüğünüze emin misiniz? Tcl'nin uplevel'i akla geliyor. Ama yine de hexten'ın cevabı çok daha iyi .. – cfi

cevap

30

Belki de bu lokalleri kullanan kodun kapanış olarak oluşturulmasını düzenleyebilirsiniz? Sonra

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! Bu retrospect içinde utanç verici açıkça :) :) Ben otomatik üreten kod olduğum için, Bu önemsiz. – Ovid

+0

Bu problemi tersine çeviren şık bir fikir! –

+0

Gerçekten,% main :: konumunu yerelleştirmek istediğiniz gibi geliyor. Bunu yapmanın bir yolu olup olmadığını merak ediyorum. –

3

Perl'e aşırı derecede aşina değilim, bu yüzden gerçekten mümkün olursa beni affet. Ancak normal olarak, bir yığın çerçevesine yerel değişkenler yalnızca bu yığın çerçevesinde kullanılabilir. Onlara daha yüksek veya daha düşük bir seviyeden erişemezsiniz (bazı hacky pointer aritmetiği yapmadıkça, ancak bu asla başarılı olmaz). Değişken bildirgelerin büyük blokları maalesef yaşamak zorunda kalacağınız bir şeydir.

QuantumPete

+1

Bu değişkenler yerleşik global değişkenlerdir. Bilindik ve tanımlandıkları için genel olarak bilişsel küresel tepkiler almazlar. Ne yazık ki, hala küresel etkiye sahipler (küresel değişkenler gibi) ve yerelleştirme mevcut kapsamdaki değişiklikleri kısıtlıyor. – Ovid

+2

Ayrıca, yerel tam olarak değil, düşündüğünüz davranışa sahip değil. local, o zamandan itibaren yerelleştirilen değişkene erişmenizi, değiştirmenizi, güncellemenizi, değiştirmenizi ve bu çağrı yığınının, yeni/değiştirilmiş değerinizde, yerelleştirilmiş olan kapanıştan ayrılana kadar devam etmesine izin verir. –

1

TCL size uplevel kullanabilirsiniz. Perl'e gelince, bilmiyorum.

+3

Neden bir TCL anahtar kelimesi için bir Wikipedia girişi var?Şimdi açmak için bir tane eklemeli miyim? :) – Ovid

+0

[Sub :: Uplevel] gibi bir şey (http://search.cpan.org/perldoc?Sub::Uplevel)? Bunun için mi? – bart

+0

Sanırım Sub :: Uplevel hiç korkmuyorum - "arayan" bir isim değil. –

6

QuantumPete'in neden zayıflatıldığından emin değil, bunun üzerinde haklı görünüyor. Çağıran satırdaki değişkenleri başlatmak için local söyleyemezsiniz. İşlevsellik özeldir ve yalnızca başlatıldığı blokta çalıştığı başlatma/yıpranmadır.

böyle Sub::Uplevel ve değişmezler için caller() "aptal" veya (sırasıyla) yüksek bir yığın karelere bir değerler 'uzun atlama dönüşü' yapmak sağlamasına izin Devel::RunBlock gibi bazı deneysel modül vardır

, ancak bunların hiçbiri bir şey yapmak local'un değişkenleri nasıl etkilediğini etkilemek için (denedim.)

Şimdilik, gerçekten ihtiyacınız olan kapsamdaki yerel bildirimlerle yaşamak zorunda kalacaksınız.

3

perldoc perlguts diyor olabilir:

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. Bunun ne kadar kolay olduğunu görmek için Alias.pm'ye yeterince bakmadım.

İlgili konular