Subroutinen in Tabelle def. und aufrufen
Nurmel
- perl
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
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
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
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
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
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
Hallo Kurt,
ist Dein Beispiel echter Perl-Code oder Pseudo-Code?
Bei mir läuft es nämlich so nicht (Syntax.-Errors).
Gruß
Nurmel
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
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
}
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.
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
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
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.
@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
Ich muss jetzt ne Woche Forenpause einlegen, nicht wundern wenn ich nicht mehr antworte...
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