2016-11-25 21 views
5

Yakalanan değişkenleri Sub::Quote tarafından oluşturulan kodda zayıflatmak istiyorum.Zayıflatma alt yazı kullanarak yakalar :: Alıntı

use 5.10.0; 
use Scalar::Util qw[ weaken ]; 
{ 
    my $s = 'foo'; 
    my $x = sub { say $s }; 
    weaken(my $y = $x); 

    my $bar = sub { &$y }; 
    &$bar; 
    $x = undef; 
    &$bar 
} 

ve çıkış:

use 5.10.0; 
use Sub::Quote; 
use Scalar::Util qw[ weaken ]; 
{ 
    my $s = 'foo'; 
    my $x = sub { say $s }; 
    weaken(my $y = $x); 

    my $bar = quote_sub('&$y', { '$y' => \$y }); 
    &$bar; 
    $x = undef; 
    &$bar; 
} 

ve çıkış:

foo 
Can't use an undefined value as a subroutine reference [...] 

Ve işte benim Alt :: Alıntı denemesi Örneğin, aşağıda olmayan alıntılanan alternatiftir

foo 
foo 

Açıkçası yakalanan $y zayıflamıyor. Yakalanan değişkenleri zayıflatmak için üretilen kodu değiştirmenin bir yolu var mı?

Belgeler seyrek ve Sub::Quote uygulaması karmaşıktır; Mevcut kodda bunun mümkün olmadığına oldukça inanıyorum, fakat yanlış olduğu görülmek isterim.

+0

'Zayıflamış' aslında bir şey yapıyor mu? Eğer işe yaradıysa, $ y' yi zayıflattıktan hemen sonra 'un' (undef) 'a dönüşmesini beklerdim. – melpomene

+0

@melpomene, CV ile ilgili ikinci bir referans var (Devel :: Peek'in 'Dump' kullanılarak görüldüğü gibi), ne olduğunu bilmeme rağmen. /// Dedi ki, '$ y = undef; ', OP'nin beklediği gibi altını serbest bırakmıyor demektir. 'Zayıflat' çağrısı demoyu etkilemeden kaldırılabilir. – ikegami

+0

@ikegami İkinci referansın option'un kendisinde olduğunu varsayalım çünkü alt kısım bir kapanış değil, bu yüzden muhtemelen derleme sırasında oluşturuldu ve sadece sonsuza dek saklandı. – melpomene

cevap

3
my $bar = quote_sub('&$y', { '$y' => \$y }); 

yaklaşık

my $bar = eval(q{ my $y = $y; sub { &$y } }); 

aynıdır (Daha yapar, ancak bu bitleri bu sorunun alakasız). Gördüğünüz gibi, bu, [1] alt bölümüne yeni bir güçlü referans oluşturur. kullanarak

my $bar = eval(q{ my $y_ref = \$y; sub { &{ $$y_ref } } }); 

Bu elde edilebilir:

Çözüm olarak

, sen dolaylama katmanı ekleyebilirsiniz

my $bar = quote_sub('&{$$y_ref}', { '$y_ref' => \\$y }); 

$y eğer herhangi bir sorun söz konusu olmaz Sub :: tarafından oluşturuldu Alıntı $y için bir takma addır. Bu Data :: Alias ​​veya 5.22'de tanıtılan deneysel bir özellik kullanılarak elde edilebilir.

Bu

aşağıdaki kullanılarak gösterilebilir:

{ 
    package Sub::Quote; 

    my $sub = sub { 
    my ($from, $captures, $indent) = @_; 
    join(
     '', 
     "use feature qw(refaliasing);\n", 
     "no warnings qw(experimental::refaliasing);\n", 
     map { 
     /^([\@\%\$])/ 
      or croak "capture key should start with \@, \% or \$: $_"; 
     (' ' x $indent).qq{\\my ${_} = \\${1}{${from}->{${\quotify $_}}};\n}; 
     } keys %$captures 
    ) 
    }; 

    no warnings qw(redefine); 
    *capture_unroll = $sub; 
} 


my $bar = quote_sub('&$y', { '$y' => \$y }); 

Sen aliasing kullanımını neden olacak bir seçenek ekleme hakkında modülün bakımcıya konuşabilirsin. Eğer bir (güçlü ya da zayıf) referans bir kopyasını oluşturduğunuzda


  1. , güçlü bir kaynaktır.
+0

Cevabımı güncelledi. – ikegami