Perl - Funktionsnamen anhand von Variablen zusammensetzen

bitmuncher

Senior-Nerd
Ich versuche gerade eine Möglichkeit zu finden, wie ich "dynamische" Funktionsnamen hinbekomme. Beispiel. Ich habe ein Array @modules, das mit Modul-Namen gefüllt ist

Code:
my @modules = ( 'modul1', 'modul2');

Ich will nun an einer Stelle entsprechende navi_-Funktionen, die Abhängig vom Modulnamen sind. In der Theorie also so in der Art:

Code:
foreach $module (@modules) {
    ...
    $navi .= &navi_$module($mycgi, $flag);
   ...
}

Natürlich gibt es auf diese Weise einen 'missing operand'-Fehler. Nur ist die Frage, wie ich das am einfachsten auf anderem Weg umsetzen kann.
 
Du könntest eval mit dem entsprechenden Funktionsaufruf als String nutzen, was allerdings eine sehr unsaubere Variante wäre. Gibt es in Perl sowas wie Makros in Lisp? Wenn ja, könntest Du damit evtl. eine sauberere Variante schreiben.
 
Also definieren kannst du in der Tat so:
Code:
@modules = ( 'modul1', 'modul2');

Ein Aufruf ginge dann so:

Code:
foreach $mod (@modules)
{
   &{$mod};
}

Der Funktionsname ist dann natuerlich zB.

Code:
sub modul1

Wenn du in der While schleife dann den Funktionsnamen entsprechend erweiterst:
Code:
foreach $mod (@modules)
{
   $bla = "nav_".$mod;
   &{$nav};
}
Kannst du die dann halt so aufrufen, wenn du eine Funktion hast:

Code:
sub nav_module1

Wenn es das ist, was du meinst. Argumente musst du global nehmen und
die, die du je Funktion brauchen wuerdest auseinanderparsen.
 
Perfekt. Genau das habe ich gesucht. Danke für den Hinweis. :) Die Syntax '&{$variable}' war mir bisher nicht bekannt. Perl hält irgendwie immer neue Überraschungen parat. ;)
 
Bist du sicher dass du es nicht lieber mit einem switch/case block loesen willst?
Dynamische Funktionsnahmen sind immer eine sehr grosse sicherheitsluecke, gerade bei Webanwendungen...

(ich denke mal dass es sich um eine Webanwendung handelt)

MFG Keks :)
 
Da in diesem Fall keine Benutzereingaben in den Funktionsnamen einfliessen, sehe ich darin kein Problem. Der Code sieht etwa so aus:

Code:
foreach my $mod_enabled ( keys %modules_enabled) {
  my $func = "navi_".$mod_enabled;
  ...
  $navi .= &{$func}($mycgi, 1);
  ...
}

Es wird also einfach nur ein Hash der aktivierten Module durchlaufen und entsprechende navi_-Funktionen angesprochen. Gibt es eine solche Funktion nicht, bricht Perl den Programmfluss ja eh ab. Ein switch-case würde dafür sorgen, dass jedesmal Änderungen an dieser Funktion gemacht werden müssten, was ich damit umgehen will. So kann ein Modul einfach eine navi_-Funktion enthalten, die einen Abschnitt für die Navigationsleiste zurück gibt und wird damit automatisch eingebunden, wenn es in %modules_enabled eingetragen ist.
 
na dann ;)

Code:
 my $func = "navi_".$mod_enabled;
$navi .= &{$func}($mycgi, 1);

kannst du uebrigens auch so schreiben:

Code:
$navi .= &{"navi_".$mod_enabled};

die ${...} schreibweise funktioniert uebrigens bei jedem Typ in perl :)

MFG - Keks
 
Es ist mir durchaus klar, dass ich das auch abkürzen kann, aber ich will den Code einigermassen nachvollziehbar machen und das Zusammenziehen von 2 Schritten zu einem trägt nicht gerade zur Übersichtlichkeit des Source bei.
 
Zurück
Oben