halfcountplus has asked for the wisdom of the Perl Monks concerning the following question:

How can I use a variable to call a subroutine with "use strict"? eg.

#!/usr/bin/perl -w #use strict; my $ref="this"; my $x=&$ref(); print "$x\n"; sub this {return "hi!"}

Replies are listed 'Best First'.
Re: variable reference to subroutine while "strict"
by FunkyMonk (Bishop) on Apr 13, 2008 at 18:00 UTC
    #!/usr/bin/perl -w use strict; my $ref=\&this; my $x=$ref->(); print "$x\n"; sub this {return "hi!"}

Re: variable reference to subroutine while "strict"
by kyle (Abbot) on Apr 13, 2008 at 19:00 UTC

    In addition to "no strict 'refs'" (which would be my first suggestion), there are a few other ways with various advantages.

    If you know all the subs you want to reference this way, you could use a dispatch table.

    my %sub_named = ( this => \&this, that => \&that, ); my $ref = 'this'; my $x; if ( exists $sub_named{ $ref } ) { $x = $sub_named{ $ref }->(); } else { # error, no sub named $ref }

    You could even make the dispatch table dynamic using eval.

    my @sub_list = qw( this that ); my %sub_named = map { $_ => eval "\\&$_" } @sub_list; # etc.

    This way, you can see what subs are available before trying to take a leap into one of them.

    You can also use eval directly.

    use English '-no_match_vars'; my $ref = 'this'; my $x = eval "&$ref()"; if ( my $error_message = $EVAL_ERROR ) { if ( $error_message =~ /^Undefined subroutine / ) { # a dispatch table would have caught this } }

    This is actually kind of clumsy. On the other hand, if you're not using a dispatch table, you might want to wrap calls in an eval anyway to catch that moment when you try to call a sub that doesn't exist.

    I haven't run and tested the code here, but it should work.

Re: variable reference to subroutine while "strict"
by tinita (Parson) on Apr 13, 2008 at 19:59 UTC
    another way:
    my $name = "this"; my $code_ref = main->can($name); $code_ref->(...);
    but i recommend using a dispatch table as shown here
Re: variable reference to subroutine while "strict"
by moritz (Cardinal) on Apr 13, 2008 at 18:05 UTC
    If you don't want strict refs, turn them off:
    my $sub_name = 'this'; my $x = do { no strict 'refs'; \&$sub_name }; print $x->(), "\n"; sub this { return "hi"; }

    Note that I kept the scope small in which I used the no strict "refs"; to prevent damage from unwanted symbolic dereferentition.

Re: variable reference to subroutine while "strict"
by pc88mxer (Vicar) on Apr 13, 2008 at 18:02 UTC
    Another way is to temporarily turn of strict-ness for refs:
    use strict; my $ref="this"; my $x; { no strict 'refs'; $x=&$ref(); } print "$x\n"; sub this {return "hi!"}
Re: variable reference to subroutine while "strict"
by ysth (Canon) on Apr 14, 2008 at 04:45 UTC
    If you want to do something strict is deliberately trying to prevent, you should turn off the stricture in question in a limited scope. This helps document that you are breaking your self-imposed rules.

    But either of the following will in fact work (the second only under some conditions):

    my $x=sub{goto &$ref}->();
    or
    my $x=&{$::{$ref}}();