2013-07-03 12 views
5

Dokumentacja wydaje się skąpa w odniesieniu do instrukcji when poza blokami given. Mówi się, że when może być używany, gdy "temat" został ustawiony, ale kiedy dokładnie temat jest uważany za zestaw? Następujące przypadki:Jakie są warunki, w których można użyć instrukcji "when" w Perlu 5?

for (@arr) { 
    when { } 
} 

Wydaje jest to ustawienie domyślne, podstawowa sprawa, ale nie mogłem dostać nawet tej pracy na mój Perl 5.14.2 - $ perl -Mfeature=switch -e 'foreach (qw(a b c)) { when (/a/) {print 'boom'} }' nie drukuje. Co ja robię źle? Okazało się, że to był kolejny problem z cytowaniem bash.

for my $elem (@arr) { 
    when { } 
} 

Czy to działa? Czy $ elem automatycznie stanie się tematem do użycia w when?

for (@arr) { 
    $_ = some_expression($_); 
    when { } 
} 

Czy to działa? Czy temat można ustawić w pętli?

Czy są jakieś różnice, gdy każdy z powyższych segmentów kodu używa foreach zamiast for?

Zasadniczo jestem bardzo niejasny w temacie tematów, więc proszę mnie oświecić.

Odpowiedz

7

To błąd konstrukcyjny polecenia powłoki.

perl -Mfeature=switch -e 'foreach (qw(a b c)) { when (/a/) {print 'boom'} }' 

powinny być

perl -Mfeature=switch -e 'foreach (qw(a b c)) { when (/a/) {print '\''boom'\''} }' 

Możemy przełączyć się cudzysłów uprościć

perl -Mfeature=switch -le'foreach (qw(a b c)) { when (/a/) {print "boom"} }' 

I możemy uprościć dalsze

perl -E'for (qw(a b c)) { when (/a/) { say "boom" } }' 

Keywords for i foreach są takie same dla Perla.

Należy zauważyć, że 5.18 oznaczone given i when jako eksperymentalne. Nie zniknie, ale się zmieni. Wyjaśniam, co się dzieje here.


Nie, when nie używa $elem; zawsze używa $_.


Tak, można zmienić $_ wewnątrz for lub given jeśli sobie tego życzą. Zauważ, że pętle foreach alaskują swój temat do odwiedzanego elementu, więc zmiana jednego z nich powoduje zmianę drugiego.

my @x = qw(abc def); 
for (@x) { $_ = uc($_); } 
say @x; # ABCDEF 
+0

Zawsze idę źle z cytatami, dzięki. Dzięki za link do innej odpowiedzi, ten i linki z tamtej strony pomogły lepiej zrozumieć status. Mam dziwny przypadek z tym: 'perl -E '@arr = qw (a b c); foreach $ x (@arr) {$ _ = $ x; $ _ ++; when (/ b /) {print $ x}} '' Wypisuje obiekt zgodnie z oczekiwaniami, ale wydaje się, że umiera z błędem" Nie można użyć, gdy() poza tematem w linii -1 ". Ten sam kod działa bez błędu (ale nic nie drukuje), jeśli usunę dwie linie za pomocą $ _. Czy mógłbyś wyjaśnić, co tu się dzieje? – sundar

+0

@sundar, Problemem nie jest wybór ofert. Problem polega na tym, że nie uciekłeś im właściwie. Zobacz aktualizację. – ikegami

+0

ta składnia dla ucieczki "jest nowa i przydatna dla mnie, dzięki. odnośnie do tematyki, dlatego wspomniałem, że "ten sam kod działa bez błędu, jeśli usunę dwie linie za pomocą $ _". Wygląda na to, że każda pętla for/foreach jest traktowana jako topicalizer, nawet dla COŚ (...), ale przypisanie do _ _ wewnątrz pętli powoduje, że jakoś tak się dzieje. – sundar

2

Ikegami dostrzegł twój rzeczywisty problem. Jeśli chodzi o inne pytania:

Dwa programy tematyczne to: for/foreach i given. Inne konstrukty, które ustawiają $_ (zmienną tematu), nie są traktowane jako obiekty do sortowania (np.map lub grep).

Jeśli uruchomisz pętlę foreach z jawną zmienną pętli, pętla nie będzie traktowana jako temat. Dlatego

for my $x (1..3) { 
    local $_ = $x; 
    say when 2; 
} 

będzie pracować dla pierwszej iteracji, ale potem umrzeć (nie można „kiedy” poza topicalizer) raz na when zostanie zamknięty.

Urządzenie given różni się tym, że nie lokalizuje $_, ale podaje leksykalny $_. Oznacza to, że given (@a) { foo; } jest podobne do { my $_ = \@a; foo; } (Myślę, że to może być naprawione).