Wolfgang: Parameter vorhanden oder nicht

Hallo!
Meine Subroutine liest die übergebenen Parameter ein mit
($p1, $p2, $p3) = @_;
Wenn $p3 nicht vorhanden ist, könnte ich dies aus der Länge des arrays erkennen, kann ich aber auch $p3 direkt abfragen, ob es übergeben wurde (vorhanden ist)?

  1. Hallo!

    Wenn $p3 nicht vorhanden ist, könnte ich dies aus der Länge des arrays erkennen, kann ich aber auch $p3 direkt abfragen, ob es übergeben wurde (vorhanden ist)?

    Begrenzt ist das über die Abfrage
    if(defined $p3)
    möglich. Begrenzt deshalb, weil diese if-Anweisung auch anschlägt, wenn eine dritte Variable zwar übergeben wurde, diese aber "undef" als Wert hatte. Spielt das eine Rolle, solltest du immer die Länge von @_ abfragen.

    Abgesehen davon, was für Vorteile versprichst du dir davon, $p3 abzufragen, anstatt die Länge von @_? Ich sehe da nichts, wo man da irgendwelche Schreibarbeit o.ä. sparen könnte...

    Grüße, Skrilax

    1. Begrenzt ist das über die Abfrage
      if(defined $p3)
      möglich.

      Folgende Variante wäre ebenso denkbar:

      sub foo {  
        my $var1 = shift || 'default';  
        my $var2 = shift || 0;  
        my $var3 = shift || undef;  
        # usw. usf.  
      }
      

      Das hat den Vorteil, dass du keine ellenlangen Abfragen nach definierten Werten machen musst oder Inkonsistenzen im Code wegen nicht übergebener Werte hast. Ansonsten neige ich zu der Variante mit (anonymen) Hashs als Übergabewert, dann hat man mit der Anzahl der Parameter keine Probleme, es ist immer nur einer.

      Siechfred

      --
      Ein Selbständiger ist jemand, der bereit ist, 16 Stunden am Tag zu arbeiten, nur um nicht 8 Stunden für einen Anderen arbeiten zu müssen.
      1. Hallo!

        sub foo {

        my $var1 = shift || 'default';
          my $var2 = shift || 0;
          my $var3 = shift || undef;
          # usw. usf.
        }

          
        Allerdings ist auch mit dieser Methode nicht wirklich erkennbar, ob nun zwei oder drei Parameter ungeachtet ihrer Werte übergeben wurden. Das geht halt nur über die Abfrage der Länge von @\_.  
          
        Grüße, Skrilax
        
        1. Allerdings ist auch mit dieser Methode nicht wirklich erkennbar, ob nun zwei oder drei Parameter ungeachtet ihrer Werte übergeben wurden. Das geht halt nur über die Abfrage der Länge von @_.

          Ja, da hast du recht. Aber wofür die Information der Anzahl der übergebenen Parameter relevant sein könnte, will mir nicht so recht einleuchten.

          Siechfred

          --
          Ein Selbständiger ist jemand, der bereit ist, 16 Stunden am Tag zu arbeiten, nur um nicht 8 Stunden für einen Anderen arbeiten zu müssen.
  2. Meine Subroutine liest die übergebenen Parameter ein mit
    ($p1, $p2, $p3) = @_;

    Du verwendest kein use strict? solltest du.

    Wenn $p3 nicht vorhanden ist, könnte ich dies aus der Länge des arrays erkennen, kann ich aber auch $p3 direkt abfragen, ob es übergeben wurde (vorhanden ist)?

    Ja, je nachdem was übergeben werden darf und was nicht. Die einfachst Variante wäre:

    sub Sub {
    my $p1 = shift;
    my $p2 = shift;
    my $p3 = shift || return;
    ....

    oder in deiner Schreibweise:

    sub Sub {
    my ($p1, $p2, $p3) = @_;
    return unless $p3;

    Das geht aber nur, wenn $p3 nicht auch Null oder ein Leerstring enthalten darf. Dann musst du, wie Skrilax schon vorschlug, auf defined prüfen.

    Struppi.

    1. Hallo,
      mein Vertrauen in Perl ist tief erschüttert!
      Ich hätte erwartet (wie bei manch anderer Sprache), dass auf einfache Weise (exists oder defined) erfragt werden kann, ob der Parameter angegeben wurde oder nicht. Und nicht auch noch so Varianten wie "Wert existiert nicht (aber vielleicht doch mit Wert 0 u,ä.)".

      1. Hallo,
        mein Vertrauen in Perl ist tief erschüttert!
        Ich hätte erwartet (wie bei manch anderer Sprache), dass auf einfache Weise (exists oder defined) erfragt werden kann, ob der Parameter angegeben wurde oder nicht. Und nicht auch noch so Varianten wie "Wert existiert nicht (aber vielleicht doch mit Wert 0 u,ä.)".

        Das hat nicht mit Perl zu tun.

        Jeder Wert der in einem boolschen Kontext ausgwertet wird ( if(Variabel) ) ist wahr, wenn er null, undefiniert oder ein Leerstring ist. Zumindest ist das in Javascript, Perl und soweit ich weiß auch in PHP so. Wenn du Wissen willst, ob überhaupt ein Wert übergeben wurde musst du in allen Sprachen eine spezielle Funktion aufrufen.

        Struppi.

        1. Wenn du Wissen willst, ob überhaupt ein Wert übergeben wurde musst du in allen Sprachen eine spezielle Funktion aufrufen.

          Meinte ich ja, es gibt in anderen Sprachen eine Möglichkeit (z.B. Standard-Funktion), die diese Information liefert.

          1. Wenn du Wissen willst, ob überhaupt ein Wert übergeben wurde musst du in allen Sprachen eine spezielle Funktion aufrufen.

            Meinte ich ja, es gibt in anderen Sprachen eine Möglichkeit (z.B. Standard-Funktion), die diese Information liefert.

            und die heißt in Perl defined()

            Struppi.

            1. und die heißt in Perl defined()

              Lt. Skrilax ist sie das ja gerade nicht:
              Zitat:
              Begrenzt ist das über die Abfrage
              if(defined $p3)
              möglich. Begrenzt deshalb, weil diese if-Anweisung auch anschlägt, wenn eine dritte Variable zwar übergeben wurde, diese aber "undef" als Wert hatte.

              1. und die heißt in Perl defined()

                Lt. Skrilax ist sie das ja gerade nicht:
                Zitat:
                Begrenzt ist das über die Abfrage
                if(defined $p3)
                möglich. Begrenzt deshalb, weil diese if-Anweisung auch anschlägt, wenn eine dritte Variable zwar übergeben wurde, diese aber "undef" als Wert hatte.

                Das stimmt nicht.

                  
                my $x = undef;  
                print (defined $x ? 'defined' : 'undef');
                

                Struppi.

                1. Hallo!

                  Begrenzt ist das über die Abfrage
                  if(defined $p3)
                  möglich. Begrenzt deshalb, weil diese if-Anweisung auch anschlägt, wenn eine dritte Variable zwar übergeben wurde, diese aber "undef" als Wert hatte.

                  Das stimmt nicht.

                  Richtig. Ich wollte sagen, dass diese if-Anweisung einen dritten Parameter eben _nicht_ erkennt, wenn er zwar übergeben wurde, aber 'undef' als Wert hatte.

                  my $x = undef;

                  print (defined $x ? 'defined' : 'undef');

                    
                  Gibt bei mir eben 'undef' aus. Wenn ich Wolfgang richtig verstanden habe, will er aber in jedem Fall erkennen, ob ein dritter Parameter übergeben wurde oder nicht, unabhängig davon welchen Wert (undef, false oder true) er hat.  
                    
                  Grüße, Skrilax
                  
                  1. Wenn ich Wolfgang richtig verstanden habe, will er aber in jedem Fall erkennen, ob ein dritter Parameter übergeben wurde oder nicht, unabhängig davon welchen Wert (undef, false oder true) er hat.

                    Dann muss er auf undef prüfen.

                    Struppi.

                  2. Gibt bei mir eben 'undef' aus. Wenn ich Wolfgang richtig verstanden habe, will er aber in jedem Fall erkennen, ob ein dritter Parameter übergeben wurde oder nicht, unabhängig davon welchen Wert (undef, false oder true) er hat.

                    Genau so habe ich es gemeint und nach meiner Meinung auch geschrieben.

                    1. Gibt bei mir eben 'undef' aus. Wenn ich Wolfgang richtig verstanden habe, will er aber in jedem Fall erkennen, ob ein dritter Parameter übergeben wurde oder nicht, unabhängig davon welchen Wert (undef, false oder true) er hat.
                      Genau so habe ich es gemeint und nach meiner Meinung auch geschrieben.

                      D.h. du möchtest deiner Funktion gerne undef übergeben und rausfinden wann du das getan hast? Wieso?

                      Struppi.

                      1. D.h. du möchtest deiner Funktion gerne undef übergeben und rausfinden wann du das getan hast? Wieso?

                        Das habe ich doch nie geschrieben!
                        Vielleicht denkst Du mal darüber nach, dass derjenige, der die Funktion schreibt, nicht selbst auch die Aufrufe der Funktionr ealisiert, sondern dass dies ganz andere tun. Und die übergeben kein undef sondern nichts. Nichts heißt nichts und nicht 0 oder "" oder undef oder sonst was.

                        1. Hallo!

                          Ich würde an der Stelle doch mal vorschlagen, dass du uns an einem kurzen aber vollständigen Beispiel erklärst, was du genau erreichen willst, v.a. wie sich die unterschiedliche Parameterzahl auswirken soll.

                          Soll bei fehlenden Parametern abgebrochen werden? Oder willst du dann mit Standardwerten weiterarbeiten? Welche Werte dürfen die optionalen Parameter haben, so sie denn übergeben werden?

                          Ich hoffe, dass wir nach Beantwortung dieser Fragen aufhören, mehr oder weniger aneinander vorbei zu reden :)

                          Grüße, Skrilax

                          1. Du hattest mich doch verstanden und mich aufgeklärt.
                            Ich habe mich danach nur gewundert, dass ich sinnvollerweise mit der Anzahl der Parameter arbeiten muss und nicht gezielt mit dem einzelnen Parameter.

                            Nervig war halt nur immer, dass meine eindeutige Fragen von Struppi mit Gegenfragen in der Art "warum", "wozu" beantwortet werden.
                            Die Aussage "der Parameter ist vorhanden bzw. übergeben" heißt nun mal im Aufruf wurde er angegeben (egal mit welchem Wert).

                            Für mich ist daher das Thema abgeschlossen, danke.

                            1. Nervig war halt nur immer, dass meine eindeutige Fragen von Struppi mit Gegenfragen in der Art "warum", "wozu" beantwortet werden.

                              Hab ich nie das gemacht, warum sollte ich so einen Blödsin tun?

                              Ich hab dir nur gesagt dass du die Möglichkeit hast, entweder mit
                              return unless $param
                              oder
                              return unless defined $param
                              zu reagieren, was davon am besten ist, hängt davon ab, ob du eine null oder einen Leerstring als Parameter akzpetierst - also deine Funktion - oder nicht. Das können wir nicht entscheiden das musst du entscheiden.

                              Daraufhin hast du gemeint "mein Vertrauen in Perl ist tief erschüttert!" und das es nicht möglich wäre in Perl zu entscheiden ob ein Wert defniert ist oder nicht, was aber einfach falsch ist.

                              Die Aussage "der Parameter ist vorhanden bzw. übergeben" heißt nun mal im Aufruf wurde er angegeben (egal mit welchem Wert).

                              Für dich mag das eindeutig klingen, aus programmiertechnischer Sicht ist das nicht so eindeutig, weil es Werte gibt (in jeder Programmiersprache) die im bool'schen Kontext falsch ergeben, aber trotzdem definiert sind. Und deine Überprüfung muss entscheiden ob diese Werte gültig sind oder nicht.

                              Für mich ist daher das Thema abgeschlossen, danke.

                              Bitte.

                              Struppi.

                            2. Ich habe mich danach nur gewundert, dass ich sinnvollerweise mit der Anzahl der Parameter arbeiten muss und nicht gezielt mit dem einzelnen Parameter.

                              Was machst du eigentlich, wenn p1 und p3 statt p1 und p2 übergeben werden? In beiden Fällen hat @_ die Länge 2.

                              Siechfred

                              --
                              Ein Selbständiger ist jemand, der bereit ist, 16 Stunden am Tag zu arbeiten, nur um nicht 8 Stunden für einen Anderen arbeiten zu müssen.
                              1. Ich habe mich danach nur gewundert, dass ich sinnvollerweise mit der Anzahl der Parameter arbeiten muss und nicht gezielt mit dem einzelnen Parameter.

                                Was machst du eigentlich, wenn p1 und p3 statt p1 und p2 übergeben werden? In beiden Fällen hat @_ die Länge 2.

                                Wobei dann p2 explizit undef sein muss. eigentlich ist das alles eine eindeutige Sache, lediglich die Rahmenbedingungen kennen wir nicht. also welche werte zugelassen werden dürfen und welche nicht, statt sich darüber auszulassen hat es der OP vorgezogen beleidigte Leberwurst zu spielen.

                                und um das ganze zu veranschaulichen:

                                test(1, 2, 3);  
                                test(1, 0, 3);  
                                test(1, '', 3);  
                                test(1, undef, 3);  
                                sub test {  
                                 my $param = scalar @_;  
                                 print "Anzahl Parameter: $param (@_)\n";  
                                 my $p1 = shift;  
                                 my $p2 = shift;  
                                 my $p3 = shift;  
                                  
                                 printf '$p1(%s)', (defined $p1 ? 'definiert' : 'undefiniert');  
                                 printf ' - $p2(%s)', (defined $p2 ? 'definiert' : 'undefiniert');  
                                 printf ' - $p3(%s)', (defined $p3 ? 'definiert' : 'undefiniert');  
                                 print "\n";  
                                  
                                 printf '$p1(%s)', ($p1 ? 'wahr' : 'falsch');  
                                 printf ' - $p2(%s)', ($p2 ? 'wahr' : 'falsch');  
                                 printf ' - $p3(%s)', ($p3 ? 'wahr' : 'falsch');  
                                 print "\n\n";  
                                }  
                                
                                

                                Struppi.

                        2. Vielleicht denkst Du mal darüber nach, dass derjenige, der die Funktion schreibt, nicht selbst auch die Aufrufe der Funktionr ealisiert, sondern dass dies ganz andere tun. Und die übergeben kein undef sondern nichts. Nichts heißt nichts und nicht 0 oder "" oder undef oder sonst was.

                          und dann ist unless defined $param genau das was du brauchst.

                          Struppi.

      2. Hallo!

        Ich hätte erwartet (wie bei manch anderer Sprache), dass auf einfache Weise (exists oder defined) erfragt werden kann, ob der Parameter angegeben wurde oder nicht.

        Da würde mich aber mal ernsthaft interressieren, was an einer Abfrage
        if(@_<3)
        denn nicht "einfach" ist?
        Bedenke dabei auch, dass @_ die einzigste Verbindung zu den übergebenen Parametern ist. Nach einer Zuweisung von @_ auf die Arbeitsvariablen hast du die Parameterliste bereits einmal kopiert, und somit diese "direkte Verbindung" aufgelöst. Somit ist diese Kontrolle auf übergebene Parameter auch nur noch indirekt über deren Werte möglich.

        Hast du schon mal was von Prototypen gehört? Vielleicht ist es ja das, was du suchst.

        Grüße, Skrilax

        1. Da würde mich aber mal ernsthaft interressieren, was an einer Abfrage
          if(@_<3)
          denn nicht "einfach" ist?

          Es ist zwar kurz aber nicht sehr sprechend.
          Und wenn mehrere Parameter optional sind , so ist es doch sicherlich erst rech verständlicher gezielt zu fragen
          if (p3 exists)  ....  if (p4 exists)
          anstatt if(@_>=3) dann p3 vorhanden, if(@_>=4) dann p4 vorhanden etc.

          1. Es ist zwar kurz aber nicht sehr sprechend.

            Wieso nicht? Es sagt dir auf einen Blick die Anzahl der Parameter.

            Und wenn mehrere Parameter optional sind , so ist es doch sicherlich erst rech verständlicher gezielt zu fragen

            Dann ist meine Variante in Verbindung mit defined das was du willst.

            if (p3 exists)  ....  if (p4 exists)
            anstatt if(@_>=3) dann p3 vorhanden, if(@_>=4) dann p4 vorhanden etc.

            if(defined p3)

            Struppi.