Seltsames Verhalten bei Rückgabe einer Liste
hotti
- perl
hi,
ich hab da eine Funktion, die checkt einen Status und gibt, wenn Status OK, drei Werte zurück (siehe untenstehend).
In der Main erwarte ich diese drei Werte und notiere:
my ($x,$y,$z) = checkit() || die $!;
Ein anschließendes
print "$x#$y#$z\n";
gibt jedoch nur den ersten Werte aus (3##), warum?
Notiere ich
my ($x,$y,$z) = checkit();
kommen alle drei Werte ganz brav an. Whats wrong!?
Hotte
sub checkit{
return(1,2,3); # alles ok
}
In der Main erwarte ich diese drei Werte und notiere:
my ($x,$y,$z) = checkit() || die $!;
my ($x,$y,$z) = checkit() or die $!;
Struppi.
»» In der Main erwarte ich diese drei Werte und notiere:
»» my ($x,$y,$z) = checkit() || die $!;
my ($x,$y,$z) = checkit() or die $!;
Jaja, das geht dann schon, mein Lieber ;-)
Aber ich frag mich nur, warum, ich hab mir mit diesem Quatsch die ganze Mittagspause vermasselt, warum nur, warum ich!!11?
Hotte
Hi
Aber ich frag mich nur, warum, ich hab mir mit diesem Quatsch die ganze Mittagspause vermasselt, warum nur, warum ich!!11?
|| evaluiert den linken Operanden scalar, (und wenn dieser falsch ist den rechten) und gibt die "wahre" Seite zurück. Außerdem hat || eine höhere präzedenz als =.
Links steht hier aber eine Liste die du mit checkit() zurückgegeben hast, also bekommst du den Scalar einer LISTE, d.h. den LETZTEN WERT!!!
(Beats Erstaunen liegt darin begründet das der Scalar eines ARRAYS die Anzahl der ARRAYELEMENTE ist, aber in Perl [leider] streng zw Array und Liste unterschieden werden muss).
Struppis Lösung mit "or" funktioniert fast genauso, allerdings mit anderer, viel geringeren Operatorpräzedenz, es entspricht
( ($x,$y,$z) = checkit() ) || die $!;
beachte das checkit für den Fehlerfall ein nacktes return;
zurückgeben muss, return 0
würde nur $x=0 setzen.
siehe auch
C-style-Logical-Defined-Or
Hi
Danke Dir für die ausführliche Infos und den Link in die Doku!
Links steht hier aber eine Liste die du mit checkit() zurückgegeben hast, also bekommst du den Scalar einer LISTE, d.h. den LETZTEN WERT!!!
Im Beispiel ja. In meinen (geänderten und nunmehr produktiven) Script, was ich heut mittag am Wickel hatte, stand jedoch der ERSTE Wert drin.
Wie auch immer, ausnahmsweise gab ich heute mal eine Liste aus ner Funktion zurück. Wo ich doch ansonsten stets mit Referenzen tu...
Viele Grüße,
Hotte
Hi
Im Beispiel ja. In meinen (geänderten und nunmehr produktiven) Script, was ich heut mittag am Wickel hatte, stand jedoch der ERSTE Wert drin.
verstehe ich nicht ... Beispiel?
Wie auch immer, ausnahmsweise gab ich heute mal eine Liste aus ner Funktion zurück. Wo ich doch ansonsten stets mit Referenzen tu...
naja es ist nicht falsches daran Listen zurückzugeben solange du es nicht in einem scalaren Kontext tust, das macht wenig Sinn!
Perl5 hat was das anbelangt Fussangeln, insbesondere bei der manchmal diffusen Unterscheidung zw. Listen und Arrays.
Aber die Doku gibt einen guten Faustregel:
nutze tendenziell ||
wenn der Rückgabewert interessiert und or
wenns nur um Ablaufsteuerung geht.
tschau
The other Rolf
Hi
»» Im Beispiel ja. In meinen (geänderten und nunmehr produktiven) Script, was ich heut mittag am Wickel hatte, stand jedoch der ERSTE Wert drin.
verstehe ich nicht ... Beispiel?
my($sid, $hugo, $ts)= $dbh->selectrow_array("SELECT sid, hugo, ts FROM sessiontable WHERE sid='$cookieValue'") || redir $fallback;
return($sid,$hugo,$ts);
In diesem Fall wird nur $sid zurückgegeben (|| redir $fallback greift nicht, alle drei Werte sind vorhanden).
Aber die Doku gibt einen guten Faustregel:
nutze tendenziell
||
wenn der Rückgabewert interessiert undor
wenns nur um Ablaufsteuerung geht.tschau
The other Rolf
Ja, Rolf, danke Dir :-)
Noch ne Faustregel, die ich heute gelernt habe: Je länger das Wochenende, desto kürzer die Woche.
Viele Grüße,
Rolf
Hi
my($sid, $hugo, $ts)= $dbh->selectrow_array("SELECT sid, hugo, ts FROM sessiontable WHERE sid='$cookieValue'") || redir $fallback;
return($sid,$hugo,$ts);In diesem Fall wird nur $sid zurückgegeben (|| redir $fallback greift nicht, alle drei Werte sind vorhanden).
naja, da fehlen mir Details, aber es würde reichen das ts==0
ist damit redir $fallback;
"greift"!
Viele Grüße,
Rolf
Um etwas konkreter zu werden, das nur $sid belegt wird ist ja klar, auf der rechten Seite berechnest du dank || einen Scalar-Wert.
»» In diesem Fall wird nur $sid zurückgegeben (|| redir $fallback greift nicht, alle drei Werte sind vorhanden).
stellt sich die Frage ob $sid wirklich den Wert für sid enthält oder du das nur vermutest.
moin Rolf,
stellt sich die Frage ob $sid wirklich den Wert für sid enthält oder du das nur vermutest.
Gestern abend noch untersucht, hier die Details:
(1)
my($sid, $hugo, $ts)= $dbh->selectrow_array("SELECT sid, hugo, ts FROM sessiontable WHERE sid='$cookieValue'") || redir $fallback;
(2)
my($sid, $hugo, $ts)= $dbh->selectrow_array("SELECT sid, hugo, ts FROM sessiontable WHERE sid='$cookieValue'") or redir $fallback;
Die Abfrage liefert exakt drei gültige Werte, die weder NULL (nicht erlaubt für sid, hugo) noch '0' (Default für ts, kommt jedoch nicht vor) enthalten.
Im Fall (1) erhalte ich nur $sid, im Fall (3) alle drei Werte (wie erwartet).
Falls Du das Problemchen nachstellen möchtest, hier die Datentypen:
sid varchar(100)
hugo varchar(100)
ts int(unsigned)
MySQL Version: 4.0.18-nt-log
Perl Version:
This is perl, v5.6.1 built for MSWin32-x86-multi-thread
Viele Grüße,
Horst
Im Fall (1) erhalte ich nur $sid, im Fall (3) alle drei Werte (wie erwartet).
Dann fragt die Funktion ab, ob du ein Array als Rückgabewert haben willst und in dem Beispiel willst du keines. Die Funktion selectrow_array düfte also in etwa so aussehen:
sub selectrow_array{ return wantarray ? ('sid','hugo', 'ts') : 'sid'; }
Struppi.
hi Struppi,
Dann fragt die Funktion ab, ob du ein Array als Rückgabewert haben willst und in dem Beispiel willst du keines. Die Funktion selectrow_array düfte also in etwa so aussehen:
sub selectrow_array{ return wantarray ? ('sid','hugo', 'ts') : 'sid'; }
Das ist eine sehr gute Idee: wantarray();
Danke und viele Grüße,
Hotte
Hi
Dann fragt die Funktion ab, ob du ein Array als Rückgabewert haben willst und in dem Beispiel willst du keines. Die Funktion selectrow_array düfte also in etwa so aussehen:
Das könnte auch sein!
Kleine pedantische Anmerkung, weil das mal wieder so eine Falle ist: "wantarray" fragt ab ob man eine LISTE als Rückgabewert haben will, die Benennung in Perl ist leider irreführend, es hätte besser "wantlist" geheißen.
Grüße
rolf
hi,
Kleine pedantische Anmerkung, weil das mal wieder so eine Falle ist: "wantarray" fragt ab ob man eine LISTE als Rückgabewert haben will, die Benennung in Perl ist leider irreführend, es hätte besser "wantlist" geheißen.
womer einmal dabei sind, lieber Rolf, erklär doch mal den Unterschied zwischen einer Liste und einem Array:...
Viele Grüße,
Rolf
Googlen verlernt? ;-)
perlfaq4#What-is-the-difference-between-a-list-and-an-array
Grob gesprochen: Arrays sind eine Datenstruktur die man in Variablen ablegen kann, Listen existieren nur "literal" und sind Scalare die mit , "gelistet" werden.. (steht da mal kein Scalar im Code, dann werden sie automatisch zu solchen flachgeklopft)
Googlen verlernt? ;-)
hehe, abschreiben gilt nich und lesen kann ich selber (sofern ich meine Brille finde) ;-)
Grob gesprochen: Arrays sind eine Datenstruktur die man in Variablen ablegen kann, Listen existieren nur "literal" und sind Scalare die mit , "gelistet" werden.. (steht da mal kein Scalar im Code, dann werden sie automatisch zu solchen flachgeklopft)
Schon besser. Wenn ich das richtig verstanden habe, muss im PerlCode ein Kommentar stehen, ob sowas da
@foo = qw(1 2 3 4 otto hannes);
eine Liste oder ein Array ist!? Ich kann das auch mit "," Komma schreiben:
@foo = (1,2,'3',4, 'otto', 'hannes');
und auch wenn ich jetzt das Ding "liste" nenne, kann ich pop(), shift() und push() anwenden, obwohl in der Doku behauptet wird, dass das mit einer "Liste" nicht machbar ist.
Isch wär blöd, hilf mir mal ;-)
Hotte
Schon besser. Wenn ich das richtig verstanden habe, muss im PerlCode ein Kommentar stehen, ob sowas da
@foo = qw(1 2 3 4 otto hannes);
eine Liste oder ein Array ist!?
nein beides: Rechts steht eine Liste, Links ein Array und in der Mitte ein Operator!
»» Schon besser. Wenn ich das richtig verstanden habe, muss im PerlCode ein Kommentar stehen, ob sowas da
»»
»» @foo = qw(1 2 3 4 otto hannes);
»»
»» eine Liste oder ein Array ist!?nein beides: Rechts steht eine Liste, Links ein Array und in der Mitte ein Operator!
Genauso stehts auch in der Dokumentation geschrieben ;-)
Nagut, das lassen wir mal so stehen.
Viele Grüße vom Baumarkt,
Horst Haselhuhn
Nagut, das lassen wir mal so stehen.
Ich weiß jetzt nicht was unklar sein könnte...
»» Nagut, das lassen wir mal so stehen.
Ich weiß jetzt nicht was unklar sein könnte...
Ja, ne, is klar, Rolf :-)
Die Perl-Dokumentation ist mir ein Heiligtum, die meinte ich mit "so stehenlassen". Meine schönen Arrays sind in Wirklichkeit zum Teil Listen, manche Listen, die ich zum Initialisieren meiner Arrays benutze sind leer, so manches meiner foreach{}-Gebilde durchläuft eine Liste und ab und zu shifte ich aus einem Array mal was unten raus und poppe ein bischen. Raider heißt nun Twix, Hugo ist in Wirklichkeit eine Frau, Westerwelle ist schwul und Schröder wixxt heimlich. Hotti ist ein bischen doof, weil er mit Mitte 50 immer noch nicht gelernt hat, dass Scheise mit 'ß' geschrieben wird, raucht dicke Zigarren obwohl Rauchen tödlich sein kann und ist der Nächste der in den wohlverdienten Ruhestand geht. Ansonsten bleibt ja alles wie es ist und das ist auch besser so.
Feierliche Grüße,
Horst Haselhuhn
freut mich geholfen zu haben ...
In der Main erwarte ich diese drei Werte und notiere:
my ($x,$y,$z) = checkit() || die $!;
Ein anschließendes
print "$x#$y#$z\n";
gibt jedoch nur den ersten Werte aus (3##), warum?
Notiere ich
my ($x,$y,$z) = checkit();
kommen alle drei Werte ganz brav an. Whats wrong!?
Der Boolean Test ist kein Listenkontext. Ausgewertet wird also
scalar @array || die;
mfg Beat
»» In der Main erwarte ich diese drei Werte und notiere:
»» my ($x,$y,$z) = checkit() || die $!;
»» Ein anschließendes
»» print "$x#$y#$z\n";
»» gibt jedoch nur den ersten Werte aus (3##), warum?
»» Notiere ich
»» my ($x,$y,$z) = checkit();
»» kommen alle drei Werte ganz brav an. Whats wrong!?Der Boolean Test ist kein Listenkontext. Ausgewertet wird also
scalar @array || die;
Ok, das Script bleibt also am Leben. Die Frage ist: Wo sind $y und $z?
Hotte
Ok, das Script bleibt also am Leben. Die Frage ist: Wo sind $y und $z?
.... und $x - denn es wird nicht, wie du vermutest, irgendein Wert aus deiner Liste ausgegeben, sondern wie Beat schon schreibt, scalar @array in deinem Fall die drei.
Struppi.
Ok, das Script bleibt also am Leben. Die Frage ist: Wo sind $y und $z?
.... und $x - denn es wird nicht, wie du vermutest, irgendein Wert aus deiner Liste ausgegeben, sondern wie Beat schon schreibt, scalar @array in deinem Fall die drei.
Was leider falsch ist. Da war ich zu schnell.
Gib als Ruckgabewerte a b c, un es wird c ausgegeben, also das letzte evaluierte Arrayelement. Und das ist mir jetzt selber schleierhaft.
my @ar = test() || die;
sub test{ return( 'a','b','c'); }
mfg Beat
hi liebe PerlFreunde,
....also das letzte evaluierte Arrayelement.
Stimmt, so isses, es kommt das "Letzte"....
Und das ist mir jetzt selber schleierhaft.
In der Zeitschrift $foo stand, glaube ich, mal ein Artikel in dem es um die Unterschiede zwischen "||" und "or" ging (Rene Bäcker), muss den mal raussuchen, http://www.perl-magazin.de/ .
Bis bald,
Hotte
Was leider falsch ist. Da war ich zu schnell.
arggl, das hab' ich bestimmt schon hundermal gelesen und schon wieder vergessen :-(
my @ar = test() || die;
sub test{ return( 'a','b','c'); }
Probier mal stattdessen:
sub test{ return( 'a','b',0); }
Struppi.