The stupid question is the question not asked PerlMonks

### Invoking a string reference to a anonymous subroutine

by Superfox il Volpone (Sexton)
 on Jan 14, 2014 at 19:03 UTC Need Help??
Superfox il Volpone has asked for the wisdom of the Perl Monks concerning the following question:

Hi there, I am defining my private methods as anonymous subs:
my $_parse_element_configuration = sub{ ... }; my$_parse_element_machines = sub{ ... };
[download]
suppose I have a reference as :
my $handler = "_parse_element_configuration"; [download] how do I invoke the anonymous sub? I am stuck with: $self->${$handler}($element); # Use of uninitialized value in method l +ookup at Configuration.pm line 59. [download] Thanks in advance for any insights, Kind regards, s.fox Replies are listed 'Best First'. Re: Invoking a string reference to a anonymous subroutine by davido (Archbishop) on Jan 14, 2014 at 19:14 UTC It seems like you're wanting a symbolic reference to refer to a lexical scalar (a my variable), which it can't directly. If, instead of 'my' you were using 'our', you could use the symbolic reference: perl -E 'our$p = sub { 1 }; my $q = "p"; say $$q->();' [download] ...but then your 'our' variable is a package global, and you're mucking around in the symbol table, which may be counterindicated for maintainability. Couldn't this problem be solved with real refs and a hash table used as a dispatch table? perl -E 'my %dispatch = ( p => sub { 1 } ); my q = "p"; say dispatch +{q}->();' [download] Dave Hi Dave > It seems like you're wanting a symbolic reference to refer to a lexical scalar (a my variable), which it can't directly. indeed... from perlref Only package variables (globals, even if localized) are visible to symbolic references. Lexical variables (declared with my()) aren’t in a symbol table, and thus are invisible to this mechanism. It never occurred to me, thanks for pointing it out! =) Cheers Rolf ( addicted to the Perl Programming Language) Re: Invoking a string reference to a anonymous subroutine by LanX (Chancellor) on Jan 14, 2014 at 20:51 UTC I prefer dispatch tables since they allow full control. Otherwise use eval to handle lexical symbolic references. The third solution shows a way to note it in one line. HTH! =) use warnings; use strict; my _parse_element_configuration = sub{ print "element_configuration: @_\n" }; my handler = "_parse_element_configuration"; my self=42; #--- dispatch table my %parser; parser{_parse_element_configuration}=_parse_element_configuration; my meth=parser{handler}; self->meth(666); #--- lex sym ref via eval meth= eval "\$$handler";$self->$meth(777); #--- abstracted sub handle { my$name=shift;
return eval "\$$name"; } handle(handler)->(self,888); [download] out: element_configuration: 42 666 element_configuration: 42 777 element_configuration: 42 888 [download] Cheers Rolf ( addicted to the Perl Programming Language) update corrected c&p problem but created duplicate! :-( #--- dispatch table ... self->meth(666); ... #--- lex sym ref via eval ... self->meth(777); [download] Don't both of these approaches take the interpreter on a useless (if there is no '42' package/class) or potentially bugilicious (if there is such a package and it contains a _whatever method) run time search through the @ISA tree? Why use the -> operator to pass an ordinary (i.e., non-class/object reference) parameter? Only #--- abstracted ... handle(handler)->(self,888); avoids this possibly lengthy detour, but substitutes eval work at runtime. Of course, I'm not sure how one would create a '42' package in the first place, but what if it had been self = 'Foo'; in your example? Hey AnomalousMonk none of this methods will ever see @ISA. :) 42 is just a dummy object, I was too lazy to fake a class for this little demo. Cheers Rolf ( addicted to the Perl Programming Language) Hi there, thanks for your replies. I have tried the third approach by Lanx, but the program returns the following error: Variable "_parse_element_configuration" is not available at (eval 8) +line 2. Use of uninitialized value in subroutine entry at Configuration.pm lin +e 64. [download] My code is : my _parse_element_configuration = sub{ ... } sub _handler{ my function_name = shift; eval "\$$function_name";
};

[...]

# invoking the handler
_handler("_parse_element_configuration")->($self,$element);
[download]
Where is the problem?

Kind regards,
s.fox

p.s. my Perl version is 5.10, could it be involved?
> Where is the problem?

My code worked and the code you are showing now will also work.

But maybe you should care to define _handler within the scope of your private $_parse... variables to have a proper closure? Otherwise Variable "$_parse_element_configuration" is not available at (eval 8) line 2."

Cheers Rolf

( addicted to the Perl Programming Language)

Re: Invoking a string reference to a anonymous subroutine
by runrig (Abbot) on Jan 14, 2014 at 19:17 UTC
You can do:Update: Ooops, no, you can't do this in your example since your subroutine does not have a name...
$self->$handler(@arguments);
[download]
Or use the code ref directly (saves a method lookup) (update: and you can do this):
$self->$_parse_element_configuration(@arguments);
[download]
You can do:

$self->$handler(@arguments);

This will only work if the anonymous subroutine reference is assigned to  \$handle and not the name of the lexical as in the OP.

Create A New User
Node Status?
node history
Node Type: perlquestion [id://1070587]
Approved by davido
help
Chatterbox?
 [thezip]: Is there an analogy for '&' (ie. run commandline process in background) for Windows commandline? [Corion]: thezip: start "some title" path\to\that\ application, but that will open another console window [Corion]: thezip: If you want to confuse your users, use system(1, "that\\command" );, which will make Perl launch it in the background [Corion]: That will keep the console window open even though the user can't type into it anymore

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (14)
As of 2017-03-27 18:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
Should Pluto Get Its Planethood Back?

Results (321 votes). Check out past polls.