Nurmel: Subroutinen in Tabelle def. und aufrufen

Hallo,
Ich möchte zu jedem Eingabefeld unterschiedlich viele Prüfroutinen definieren und in der Prüfroutine in einer Schleife über die Felder und innerhalb über die zugehörigen Prüfungen die Felder überprüfen. Wie kann ich das am besten anstellen.
Insbesondere wie kann ich eine  Subroutine aufrufen, deren Namen ich in einer Variablen stehen habe, aufrufen?
Mit schönen Grüßen zum Wochenende
Nurmel

  1. Hi

    Insbesondere wie kann ich eine  Subroutine aufrufen, deren Namen ich in einer Variablen stehen habe, aufrufen?

    es gibt eine saubere und eine (intuitivere) nonstrict Methode.

    Die saubere, lege ein Array von Referenzen auf deine Routinen ab.

      
    sub pruef_es {  
    }  
      
    sub pruef_es_auch {  
    }  
      
    #zuweisung  
    %pruef{feld_1}=[\&pruef_es];  
    %pruef{feld_2}=[\&pruef_es,\&pruef_es_auch];  
      
    #aufruf  
    for $code_ref ( @$pruef{feld_x} ) {  
       &$code_ref(feld_x,paras);    # variante 1  oder alternativ  
       $code_ref->(feld_x,paras);   # variante 2  
    }  
    
    

    Habe ich dir weitergeholfen???

    Grüße
     Kurt

    1. Hallo,

      Habe ich dir weitergeholfen???

      Ächz,stöhn,
      noch verstehe ich nichts, insbesondere $code_ref und &$.....
      Ich werde mal versuchen, dies so 1 zu 1 zu testen.
      Danke
      Nurmel

      1. Hi

        OK du kannst wie gesagt auch nonstrict arbeiten mit Perlref Symbolic references

        Also ich hab dir ne Komplettlösung hingeschrieben, die details findest du in in Perlref.

        Entscheide bitte selbst!

        Grüße
         Kurt

        1. Moin Moin!

          Hi

          OK du kannst wie gesagt auch nonstrict arbeiten mit Perlref Symbolic references

          Das würde ich nicht empfehlen, es gibt gute Gründe für strict, aber hier keinen Grund, strict abzuschalten. Mit Referenzen wird der Fragesteller früher oder später ohnehin arbeiten müssen, also wird er sie ohnehin mal lernen und verstehen müssen. Auch die Ampersand-Notation aus Perl4 würde ich nicht einsetzen, die irritiert nur.

          $coderef->(arguments) ist der Weg, analog zu $arrayref->[index] und $hashref->{key}.

          Falls C-Vorwissen vorhanden ist: Eine Referenz ist ein Zeiger mit Typprüfung und Referenzcounter.

          Alexander

          --
          Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
          1. Hi

            Das würde ich nicht empfehlen,

            ich empfehle es auch nicht ich bin nur ausführlich.

            Auch die Ampersand-Notation aus Perl4 würde ich nicht einsetzen, die irritiert nur.
            $coderef->(arguments) ist der Weg, analog zu $arrayref->[index] und $hashref->{key}.

            Wie gesagt, ich bin nur ausführlich. Bei einem einfachen Zugriff reicht ein ->
            aber es gibt immer wieder Fälle wo man an Sigils wie & , @ oder % nicht vorbeikommt.

            Ciao
             Kurt

        2. Hallo Kurt,
          ist Dein Beispiel echter Perl-Code oder Pseudo-Code?
          Bei mir läuft es nämlich so nicht (Syntax.-Errors).
          Gruß
          Nurmel

          1. Hi

            ist Dein Beispiel echter Perl-Code oder Pseudo-Code?

            ungeprüfter Perlcode, das dauert sonst zu lange

            Bei mir läuft es nämlich so nicht (Syntax.-Errors).

            ... andererseits ist perlsyntax zu dicht um Edit-Fehler sofort visuell zu erkennen.

            Du solltest ja auch was tun :-)

            Naja try this

              
            use strict;  
            use warnings;  
            $\="\n";  
              
            sub pruef_es {  
             print "pruef_es(",@_,")";  
            }  
              
            sub pruef_es_auch {  
             print "pruef_es_auch(",@_,")";  
            }  
              
              
            #zuweisung  
            my %pruef;  
            $pruef{feld_1}=[\&pruef_es];  
            $pruef{feld_2}=[\&pruef_es,\&pruef_es_auch];  
              
            #aufruf  
            for my $code_ref ( @{$pruef{feld_2}} ) {  
               $code_ref->('feld_1','paras');   # variante 2  
            }  
              
            
            

            OUTPUT:
            pruef_es(feld_1paras)
            pruef_es_auch(feld_1paras)

            ciao
             Kurt

            1. Hi

              Naja vielleicht ist folgendes weniger allgemeines Beispiel für dich einfacher zu verstehen

                
              use strict;  
              use warnings;  
              $\="\n";  
                
              sub pruef_es {  
               print "pruef_es(",@_,")";  
              }  
                
              sub pruef_es_auch {  
               print "pruef_es_auch(",@_,")";  
              }  
                
              #zuweisung  
              my @feld_1=( \&pruef_es );  
              my @feld_2=( \&pruef_es , \&pruef_es_auch );  
                
              #aufruf für feld2  
              for my $code_ref ( @feld_2 ) {  
                 $code_ref->('feld_2','paras');   # variante 2  
              }  
                
               
              
              1. Hallo Kurt,
                danke für Deine Hilfe. Welche Erfahrung braucht man, bis man so ein Script spontan hinschreiben kann?

                Naja vielleicht ist folgendes weniger allgemeines Beispiel für dich einfacher zu verstehen

                Danke, ja, das verstehe ich so leidlich.
                Beim anderen Beispiel ist mir allerdings folgendes völlig schleierhaft:

                #aufruf
                for my $code_ref ( @{$pruef{feld_2}} ) {
                   $code_ref->('feld_1','paras');   # variante 2
                }

                Ich hatte spontan angenommen, dass dies eine Schleife über die Felder und über die zugehörigen Prüfungen ist,
                dass es also dem
                #aufruf für feld1     u n d
                #aufruf für feld2
                aus dem einfacheren Beispiel entspricht.
                Allerdings hat mich dann die Angabe von feld_2 und feld_1 im obigen Ausdruck verwirrt.

                1. Hi

                  Allerdings hat mich dann die Angabe von feld_2 und feld_1 im obigen Ausdruck verwirrt.

                  Flüchtigkeitsfehler, das sollte nur der Aufruf der Rotinen für *ein* feld sein. Für die einzelnen Felder musst du halt noch ne Schleife drumrum bauen.

                  lies dir auch mal die Perl-Doku durch, dann siehst du klarer:
                  perlref
                  perldsc

                  grüße
                   kurt

                  PS: auch auf deutsch erhältlich http://faq.perl-community.de/bin/view/Perldoc/perldsc

                  1. Hallo,

                    lies dir auch mal die Perl-Doku durch, dann siehst du klarer:
                    perlref
                    perldsc

                    Ja, damit habe ich mir den ganzen Sonntag versaut - und die Laune meiner Frau!
                    Aber ich bleibe dran. Hab auch schon einige vergebliche Versuche gestartet mit
                    diesen Hyroglyphen $@%!
                    Schöne Woche
                    Nurmel

                    1. Hi

                      Aber ich bleibe dran. Hab auch schon einige vergebliche Versuche gestartet mit
                      diesen Hyroglyphen $@%!

                      hör mal so schwer ist es nicht, Perl realisiert verschachtelte Strukturen mit Referenzen.

                      ==== Schritt 1

                        
                      $pruef{'feld_1'}=[ $code_ref1,$coderef2 ];
                      

                      baut ein Hash mit dem Key 'feld_1' auf mit einem Array von Codereferenzen als Eintrag.

                      [] liefert die Refrenz auf ein anonymes Array du hättest auch schreiben können

                        
                      @sub_list=($code_ref1,$coderef2);  
                      $pruef{'feld_1'}=\@sub_list;
                      

                      @code_refs wäre aber benannt und nicht anonym.

                      ==== Schritt 2

                      greifts du auf $pruef{'feld_1'} zu erhälst du also eine Refrenz auf ein array.

                      um die Refrenz zu dereferenzieren schreibts du wieder ein @ davor.

                      Also entweder:

                      $sub_list_ref= $pruef{'feld_1'};  
                      @sub_list = @{$sub_list_ref} ; # hier könntest du die {} auch weglassen
                      

                      oder aber gleich kürzer

                      @sub_list = @{ $pruef{'feld_1'} } ; # hier könntest du die {} NICHT weglassen

                      ==== Schritt 3

                      die for Schleife braucht eine Liste also

                        
                      for $code_ref ( @{ $pruef{'feld_1'} } )  
                      
                      

                      ich hab mal ne Übersicht geschrieben:
                      http://board.perl-community.de/thread/11304/startWithMessage=10#MSG15

                      In Perl sind die Datenstrukturen primär listenorientiert, nicht Refrenzen wie in den meisten anderen Sprachen, d.h. du musst sie explizit in Referenzen überführen um sie zu schachteln oder zu übergeben.

                      http://board.perl-community.de/thread/11291/startWithMessage=11

                      DER TRICK IST ALSO: Denk gleich in Refrenzen die du nur bei Bedarf in die "Listenform" überführst.

                      schreib jetzt ein bisschen Code dann bekommst dus auch hin und wenn etwas nicht klappt dann poste ihn  und dir wird geholfen.

                      Bye
                       Kurt

                      PS: nein ich habe den Code nicht vorher ausprobiert.

                      1. @sub_list=($code_ref1,$coderef2);
                        $pruef{'feld_1'}=@sub_list;

                        
                        >   
                        > @code\_refs wäre aber benannt und nicht anonym.  
                          
                        refactoringfehler @code\_refs heißt jetzt @sub\_list
                        
                        1. Ich muss jetzt ne Woche Forenpause einlegen, nicht wundern wenn ich nicht mehr antworte...

  2. Insbesondere wie kann ich eine  Subroutine aufrufen, deren Namen ich in einer Variablen stehen habe, aufrufen?

    Evtl. hilft Dir mein kleiner Codeschnipsel:
    http://anaboe.net/codes/perl/name-einer-subroutine-als-string

    Siechfred

    --
    Hinter den Kulissen passiert viel mehr, als man denkt, aber meistens nicht das, was man denkt.