Can I call a routine on a hard-coded address in Perl?

Say I have the following code snippet:

my $compiled = eval 'sub { print( "Hello World\n" ); }'; 

I can call it by writing:

 $compiled->(); 

So far so good. Now imagine that I am creating 10 functions:

 my @fns = (); for ( my $i = 0; $i < 10; $i++ ) { push( @fns, eval "sub { print( 'I am function $i\n' ); }" ); } 

I can name these 10 functions as follows:

 foreach ( @fns ) { $_->(); } 

Now I want to create a dynamic function that explicitly calls each of my 10 functions:

 my $evalcode = "sub {"; foreach ( @fns ) { # if I print $_ it shows something like # "CODE(0x94084f8)", but trying to # call "CODE(0x94084f8)->()" is invalid $evalcode .= "$_->();"; } $evalcode .= "}"; my $dynamic_fn = eval $evalcode; $dynamic_fn->(); 

Is it possible to take a gated link to a subprogram and call it directly?

PS why, you ask? Since I would like to write a dynamic routine that builds a chain of if ( m/.../ ) { } elsif ( m/.../ ) { } ... checks, which then call dynamic functions depending on the input string.

+4
source share
5 answers

Instead of evals strings, you can use regular lexical closures:

 my @functions; for my $i (0 .. 9) { push @functions, sub { print "I am function $i\n" }; } my $call_all_funcs = sub { for my $func (@functions) { $func->(); } }; $call_all_funcs->(); 

You can also get a link to the code based on its address, but that would be much more complicated, difficult to understand and not a good idea at all.

+14
source

How to use closure instead of eval string?

 sub combine_subrefs { my @subs = @_; return sub { foreach my $subref (@subs) { $subref->() } }; } my $dynamic_fn = combine_subrefs( @fns ); $dynamic_fn->(); 

I am sure that you can adapt this to do the same as you.

+8
source

re: why, you ask? Since I would like to write a dynamic routine that builds a chain if (m /.../) {} elsif (m /.../) {} ... will check, which then calls the dynamic functions depending on the input string.

To create an if and elsif chain similar to the one described above, you can do it without resorting to eval :

 use 5.012; use warnings; my $build_ifelse_dispatch_table = sub { my @functions = @_; sub { my $text = shift; for (@functions) { my ($re, $code) = @$_; if ($text =~ $re) { $code->(); last; } } }; }; my $dispatch_on = $build_ifelse_dispatch_table->( [ qr/tom/ => sub { say "Tom!" } ], # if (m/tom/) { ... } [ qr/dick/ => sub { say "Dick!" } ], # elsif (m/dick/) { ... } [ qr/harry/ => sub { say "Harry!" } ], # elsif (m/harry/) { ... } ); $dispatch_on->( 'peeping tom' ); # Tom! $dispatch_on->( 'spotty dick pudding' ); # Dick! $dispatch_on->( 'harry potter' ); # Harry! $dispatch_on->( 'Tom, dick and harry' ); # Dick! 

ref: Wikipedia entry Distribution table .

/ I3az /

+7
source

When you print a subroutine link, you see something like CODE(0xDEADBEEF) , since Perl builds links. You see something like if you print some link that does not overload the structure:

  $ perl -le 'print []' ARRAY(0x1008032b8) 

Usually you cannot use this value for anything, and the number you see does not match the required real memory address.

What you do, see the dynamic routine chapters that I have in Mastering Perl. I’ll talk in some detail about the various things you can do to create routines and work with anonymous routines. A module, such as Data :: Constraint , may even give you some ideas. I also talk about this in my answer to How can Perl get its caller back? .

+4
source

Perhaps this is possible (see this similar problem and solutions ), but perhaps there is another way. What about a hash (global?) That displays string links to links to actual code links?

 my @fns = (); for ( my $i = 0; $i < 10; $i++ ) { my $fn = eval "sub { print('I am function $i\n'); } "; if (ref $fn eq 'CODE') { $CODETABLE{$fn} = $fn; } push @fns, $fn; } ... my $evalcode = "sub {"; foreach ( @fns ) { # convert stringified code ref to the actual code ref $evalcode .= "\$CODETABLE{\"$_\"}->();"; } $evalcode .= "}"; (eval $evalcode)->(); 

 I am function 0 I am function 1 I am function 2 I am function 3 I am function 4 I am function 5 I am function 6 I am function 7 I am function 8 I am function 9 
+1
source

All Articles