ubuntuusers.de

Perl: Subname als Variable interpolieren

Status: Gelöst | Ubuntu-Version: Nicht spezifiziert
Antworten |

Sebastian1234

Anmeldungsdatum:
29. September 2006

Beiträge: 92

Wohnort: Berlin

Hallo,

ich erlaube mir eine Perl Frage, weil die Leute hier einfach schneller sind! ♥

Ich übergebe den Name einer Subroutine an eine andere Subroutine.

sub perl_help
 	{
	my $result; 
        #
        # $_[0] ist der String test $_[1] ist der string uebergabe
        #
 	$result = $_[0]($_[1]);  # Das soll passieren: $result = test(uebergabe);
        #
	};

In der Variable Result soll also der Return der sub "test", deren Name mit $_[0] übergeben wird gespeichert werden.

Nur als Minimalbeispiel. Ich bearbeite die Daten in der sub perl_help noch weiter,
so dass es für mich schon irgendwie Sinn machen würde...

Grüße
Sebastian1234

audax

Avatar von audax

Anmeldungsdatum:
15. September 2006

Beiträge: 1253

Du kannst die Referenz einer Subroutine übergeben!

sub perl_help
 	{
        my($func_ref, $foo) = @_;
        my $result; 
        # das '&' sagt perl, das der String 'func_ref' eine Referenz
        # auf eine Funktion ist
 	$result = &{$func_ref}($foo);
	};

sub foobar{ s/foo/bar };

# perl_help wird eine Funktionsreferenz und string übergeben
# das '&' sagt perl, dass sie Funktion und nicht ihr Rückgabewert gemeint ist
print perl_help(\&foobar, 'bar')

Mehr dazu steht in 'perldoc perlref', wofür du das Paket 'perl-doc'
installieren musst.

Sebastian1234

(Themenstarter)

Anmeldungsdatum:
29. September 2006

Beiträge: 92

Wohnort: Berlin

Hallo,

ja so komme ich auf den richtigen Weg.

Aktuell noch:

Can't use string ("calc_day_from_date") as a subroutine ref while "strict refs" is used.

Werde lesen!

Grüße
Sebastian1234

Sid_Burn

Anmeldungsdatum:
23. Oktober 2004

Beiträge: 2159

$result = &{$func_ref}($foo);


Sowas schreibt man nicht mehr. Also erstens kannst du die Geschweiften Klammern weg lassen, und zweitens derefenrenziert man mit dem Pfeil. Mit einem & ruft man keine Funktionen mehr auf, da es "out-of-date" ist und noch paar nebenwirkungen hat.

$func_ref->($foo)

Can't use string ("calc_day_from_date") as a subroutine ref while "strict refs" is used.

Dann hast du die Übergabe falsch gemacht. DU musst beim Subroutinen aufruf nicht den Namen der Subroutine übergeben, sondern die Referenz!

Die Referenz einer Subroutine bekommst du wenn du \& vor dem Subroutinen namen schreibst. Also z.B. so:

$func_ref = \&meine_subroutine

oder halt direkt in eine Subroutine eingebaut folgendermaßen:

meine_subroutine( \&callback_function )

Übrigens wenn du selber Funktionen für die Zeit/Datums Berechnung machst, dann würde ichd avon die Finger lassen. Berechnung mit Zeit/Datum sind ziemlich komplex. Wenn du sowas machst, würde ich mir lieber das Modul DateTime anschauen.

Sebastian1234

(Themenstarter)

Anmeldungsdatum:
29. September 2006

Beiträge: 92

Wohnort: Berlin

Hallo,

danke das hat geholfen.
Läuft tadellos.
Lese trotzdessen... versprochen... 😇

Verwende das Time Modul.
Also die obige sub nutz dies.

Grüße
Sebastian1234

audax

Avatar von audax

Anmeldungsdatum:
15. September 2006

Beiträge: 1253

Sid Burn hat geschrieben:

$result = &{$func_ref}($foo);


Sowas schreibt man nicht mehr. Also erstens kannst du die Geschweiften Klammern weg lassen, und zweitens derefenrenziert man mit dem Pfeil. Mit einem & ruft man keine Funktionen mehr auf, da es "out-of-date" ist und noch paar nebenwirkungen hat.

Nebenwirkungen?
Und das mit den geschweiften Klammern Um Referenzen hab ich aus BestPractices, so allgemein für Referenzen...jedenfalls in Erinnerung. Webei du schon Recht hast, jap. Ich glaube, das war da anders gemeint 😳
Hab einfach blind das erste Beispiel aus perlref zitiert...

Die Pfeile sind besser.
@Threadstarter:
Hör auf Sid 😉

Sid_Burn

Anmeldungsdatum:
23. Oktober 2004

Beiträge: 2159

Nebenwirkungen?

Jup.

$func->($foo)
&$func($foo)

Diese beiden Sachen sind noch identisch.

$func->()
&$func

Diese nicht mehr.

Wenn man eine Subroutine mit einem & aufruft und keine Argumente übergibt dann wird immer automatisch das Array (@_) übergeben. Sprich die aktuelle Argumentenliste. Und das kann zu Nebenwirkungen führen die man nicht sofort sieht. Ich weiß jetzt gar nicht ob @_ auch übergeben wird wenn man eine Leere Klammern hinzufügt. Aber egal ob es das tut oder nicht. Es wäre kein Vorteil wenn sich leere Klammern komplett anders verhalten wie das weg lassen der Klammern. Wie gesagt sowas ist absolut nicht empfohlen.

Deswegen immer mit nem Pfeil dereferenzieren. Aber das mit dem & ist aber auch schon uralt und stammt eher aus Perl 4 Zeiten. Ich meine nichtmal "Einführung in Perl" das auch schon recht veraltet ist sagt einem das man Subroutinen mit einem & aufrufen soll.

Und das mit den geschweiften Klammern Um Referenzen hab ich aus BestPractices, so allgemein für Referenzen...

Also eigentlich nicht. 😉

Aus dem Kapitel Subroutinen heißt die erste Regel "Rufen Sie Unterroutinen mit Klammern, aber ohne führendes & auf."

Und aus dem Kapitel Referenzen heißt die erste Regel. "Dereferenzieren Sie möglichst immer mit Pfeilen".

"Möglichst immer" deswegen weil es ja nicht immer möglich ist, mit dem Pfeilen genau das auszudrücken was man meint.

Ansonsten dient das Buch ja nur dazu um über seinen Code darüber nachzudenken ob das was man geschrieben hat lesbar genug ist. Bzw. es werden ja auch Vor/Nachteile genannt der einzelnen Sachen. Es ist ja keine heilige Schrift an der man sich halten muss. 😉 Ich selber nutze z.B. auch nicht "$objekt->foo()->bar()->welt()" da ich sowas häßlich finde. ich schreibe dann auch eher "$objekt->foo->bar->welt"

audax

Avatar von audax

Anmeldungsdatum:
15. September 2006

Beiträge: 1253

Ach..das mit dem 'immer Klammern drum!' war glaube ich die Sache mit dem FH für print...naja, habs grad nicht hier 😉

Ich hab übrigens grad mal in meinem Code nachgeschaut, da derefenziere ich immer mit dem Pfeil 😮

Antworten |