hotti: Seltsames Verhalten bei Rückgabe einer Liste

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
}

--
Wenn der Kommentar nicht zum Code passt, kann auch der Code falsch sein.
  1. In der Main erwarte ich diese drei Werte und notiere:
    my ($x,$y,$z) = checkit() || die $!;

    my ($x,$y,$z) = checkit() or die $!;

    Struppi.

    1. »» 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

      --
      Wenn der Kommentar nicht zum Code passt, kann auch der Code falsch sein.
      1. 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

        1. 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

          --
          // hier meckert Perl
          1. 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

            1. 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 und or 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

              --
              # Name geändert
              1. 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

                1. 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.

                  1. 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

                    $Id: DBD.pm,v 11.16 2003/05/14 11:08:17 timbo Exp $

                    Viele Grüße,
                    Horst

                    --
                    Ein Blitz zerlegte den Airbus in tausende Einzelteile.
                    1. 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.

                      1. 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

                        --
                        Want a Cigar.
                      2. 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

                        1. 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

                          --
                          Wenn der Kommentar nicht zum Code passt, kann auch der Code falsch sein.
                          1. Googlen verlernt? ;-)

                            list vs array

                            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)

                            1. Googlen verlernt? ;-)

                              list vs array

                              perlfaq4#What-is-the-difference-between-a-list-and-an-array

                              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

                              --
                              Wenn der Kommentar nicht zum Code passt, kann auch der Code falsch sein.
                              1. 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!

                                1. »» 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

                                  --
                                  Eine Pfette ist auch nur eine Latte.
                                  1. Nagut, das lassen wir mal so stehen.

                                    Ich weiß jetzt nicht was unklar sein könnte...

                                    1. »» 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

                                      --
                                      Zähne fliegen beim Putzen nicht weg, wenn sie mit der Hand festgehalten werden.
                                      1. freut mich geholfen zu haben ...

  2. 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

    --
    ><o(((°>           ><o(((°>
       <°)))o><                     ><o(((°>o
    Der Valigator leibt diese Fische
    1. »» 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

      --
      # bitte ignorieren
      1. 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.

        1. 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

          --
          ><o(((°>           ><o(((°>
             <°)))o><                     ><o(((°>o
          Der Valigator leibt diese Fische
          1. 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

            --
            # Überraschung:
          2. 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.