Listen Operator Priorität in Perl

8

Ich lese das Buch "Beginning Perl", und es gibt diese zwei Aussagen:

%Vor%

Die erste Zeile druckt nichts mit einer neuen Zeile, die zweite Zeile druckt eine 1 ohne neue Zeile.

Ich bin verwirrt über die Ausgabe. Laut dem Autor gibt die zweite Aussage seltsame Ergebnisse, weil es wie gesagt ist:

%Vor%

Aber warum ist die erste Aussage nicht die gleiche? Ich dachte, es hätte etwas mit der Priorität des Drucks zu tun. Die & amp; & amp; hat Vorrang vor Druck, also wird zuerst ausgewertet und dann gedruckt. Während das "und" eine niedrigere Priorität hat als das Drucken, so 6 & gt; 3 wird gedruckt, print gibt eine 1 zurück, und dann wird das mit "und" ausgewertet. Das macht jedoch keinen Sinn.

Ich habe die Perl-Dokumentation gelesen, wie die Präzedenz für Listenoperatoren funktioniert, aber ich verstehe dieses Beispiel immer noch nicht. Können Sie die beiden Aussagen sezieren und mir sagen, was zuerst gedruckt wird? Kannst du auch erklären, was die Perl-Dokumentation bedeutet, wenn sie Listenoperatoren als "links" und "rechts" bezeichnet? Danke.

Vielen Dank für Ihre Antworten. Ich verstehe es jetzt. Ich tat tatsächlich, was CJM sagte, und dachte, dass es Links und Rechts-Listen-Operatoren gibt. So, jetzt, wo ich verstehe, was es bedeutet, verstehe ich die ganze Sache.

    
Brian 09.08.2010, 07:04
quelle

3 Antworten

12

Okay, für den Anfang: Listenoperatoren gehören zu den Dingen mit der geringsten Präzedenz in Perl, aber nur auf ihrer rechten Seite . Sie fragen, was das heißt: Nun, machen wir es einfach. Angenommen, es gibt eine Liste namens foo . Es ist egal, was es tut, aber es ist da. Sie können so etwas mit sub foo { map 10 * $_, @_ } erstellen, das jedes seiner Argumente mit zehn multipliziert. Das ist aus dem Weg:

print 1, 2, 3; entspricht print( 1, 2, 3 );
print foo 1, 2, 3; entspricht print( foo( 1, 2, 3 ) );
print 1, foo 2, 3; entspricht print( 1, foo( 2, 3 ) );

Wir können sehen, dass foo so viel verschlingt, wie es auf der rechten Seite möglich ist - nur das Ende der Anweisung (bis jetzt ...) kann es stoppen. Wenn wir @array = (1, foo 2, 3); schreiben würden, wäre das gleichbedeutend mit @array = (1, foo(2, 3) ); , da natürlich das Ende der umgebenden Klammern immer noch gilt.

Da Kommas auch eine sehr niedrige Priorität haben (knapp über "Listenoperatoren (rechts)"), können wir auch so ziemlich jede Art von Ausdruck in die Argumente eines Listenpunkts einfügen - das ist nur eine Möglichkeit, dies sicherzustellen Wir müssen die meiste Zeit keine Klammern hinzufügen. Mathe, bitweise Operatoren, Vergleiche, sogar Regex-Übereinstimmungen haben höhere Priorität.

Die einzigen Dinge, die tun haben eine niedrigere Priorität sind die ausgeschriebenen logischen Verbindungen and , or , xor und not . Also wenn wir

schreiben %Vor%

das bedeutet (foo(1, 2, 3) and 4) - die Argumente für foo stehen links von and . Das scheint in einem erfundenen Beispiel albern zu sein, also machen wir es zu einem gewöhnlichen Perl-Idiom:

%Vor%

was äquivalent zu

ist %Vor%

was eigentlich genau äquivalent ist (und kompiliert zu)

%Vor%

mit der Anweisung-Modifikator-Form von unless (die überhaupt kein Operator ist, ist nur einmal pro Anweisung erlaubt und kommt nur am Ende einer Anweisung, so dass sie nicht wirklich Vorrang vor hat alles, aber Sie könnten es als "niedriger als niedrigste" Priorität nach links betrachten.

Wie auch immer, zurück zu Ihrem ursprünglichen Codebeispiel - die Argumente zu print enden direkt links von and und rechts von and ist ein völlig separater Komma-Ausdruck - der überhaupt nichts tut weil es nur ein paar Konstanten 3 > 4 und "\n" im void Kontext ausgewertet werden.

    
hobbs 09.08.2010, 09:29
quelle
8

So würden diese Anweisungen mit vollen Klammern aussehen:

%Vor%

> hat die höchste Priorität, dann && , dann , , dann print , dann and .

6 > 3 ergibt 1 . 3 > 4 ergibt false, was in Perl ein spezieller Wert ist, der in einem numerischen Kontext 0 ist, aber die leere Zeichenfolge in einem Zeichenfolgenkontext (wie hier). So liefert ((6 > 3) && (3 > 4)) den leeren String.

Somit übergibt die erste Anweisung 3 Argumente an print : "Test one: " , die leere Zeichenfolge und eine neue Zeile. Es druckt jedes Argument der Reihe nach.

Die zweite Anweisung übergibt nur 2 Argumente an print : "Test two: " und 1 . Die neue Zeile wird nicht gedruckt, da sie nie an print übergeben wurde.

Ich bin mir nicht sicher, wie ich "nach links" und "nach rechts" besser erklären könnte als die Docs . Aber vielleicht verwirren Sie, dass Sie denken, dass es "Links-Listen-Ops" und "Rechts-Listen-Ops" gibt. Das ist nicht was es bedeutet. Es versucht zu sagen, dass alles auf der rechten Seite eines Listenoperators als Argumente für diesen Operator interpretiert wird (es sei denn, Sie treffen einen der Booleschen Operatoren mit sehr niedriger Priorität wie and ). Aber Dinge auf der linken Seite eines Listenoperators sind nicht mit diesem Listenoperator verbunden.

    
cjm 09.08.2010 07:36
quelle
4

Es ist wie du sagst, außer dem "das macht keinen Sinn" -Teil.

Der erste ist

%Vor%

und der zweite

%Vor%

Wenn Sie Warnungen ( use warnings ) aktivieren, erhalten Sie die Warnung Useless use of a constant in void context , weil die rechte Seite von and zu einer Liste mit Elementen false und einer neuen Zeile aber nicht ausgewertet wird jemals benutzt.

Bearbeiten : Mein Anspruch 3 & gt; 4 ist undef wurde korrigiert. Falsch ist nicht undef. Es ist definiert und druckt nichts.

    
musiKk 09.08.2010 07:39
quelle

Tags und Links