2017-12-21 4 views

Antwort

3

Es gibt nur einen Zyklus.
Es sammelt alle Zeilen als Schlüssel in %l, mit den Werten wie oft es es gesehen hat.
Wenn dies das erste Mal ist (… == 1), ist es auf eine Kopie der aktuellen Zeile gestoßen, die es druckt.

Es funktioniert im Grunde das gleiche wie:

my %l; 

for $*ARGFILES.lines() { # this is basically what `-n` does 

    ++%l{ $_ };    # update the count 

    .say if %l{ $_ } == 1; # print it if this is the first time it was seen 

} 

Ich denke, der Grund … if ++$… == 1 statt … unless $…++ verwendet wurde, ist, dass &prefix:«++» etwas performanter als &postfix:«++»


Eine andere potentiell effizienter (je auf die Implementierung von .unique) Weg, es zu schreiben wäre:

perl6 -e '.put for $*ARGFILES.lines.unique' input-file.txt 
+0

Dank! Ich habe die Logik falsch verstanden, obwohl es in der Tat sehr einfach ist. –

+0

Kein Aufruf von Zeilen auf '$ * ARGFILES', wenn Sie nur' lines() 'aufrufen, wird es bereits auf' $ * ARGFILES' operieren. – timotimo

2

Lassen Sie uns dies ein wenig entpacken. Die -n Option fügt eine for lines() { ... } Schleife um den Code, so haben wir

for lines() { 
    state %l; 
    .say if ++%l{$_} == 1 
} 

Warum ein state var? Es gibt keine einfache Möglichkeit, eine Variable in einem äußeren Bereich der impliziten Schleife dieser einen Zeile zu deklarieren. Andernfalls würden Sie schreiben, dass als

my %l; 
for lines() { 
    .say if ++%l{$_} == 1 
} 

%l Überblick über die Anzahl der Male hält eine Leitung (gespeichert in $_) gesehen wurde. Es verwendet Autovification. Wenn also zum ersten Mal eine Zeile angezeigt wird, fügt der Operator ++ diese automatisch zum Hash hinzu.

.say ist eine Abkürzung für $_.say

+0

Danke! Was bedeutet '()' nach 'Zeilen'? –

+1

Das 'Linien' nimmt keine Argumente. Dies wird in dieser Situation benötigt, weil sonst das '{}' als ein Argument für das 'Linien'-Sub verwendet werden würde. –

Verwandte Themen