http://www.perlmonks.org?node_id=479282

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

Hi Monks,

I am getting very confusion with the error.

use strict; my $SubroutName='test'; my $text='abcdefgijkl'; &$SubroutName($text); sub test{ print "\nokey!"; } sub test1{ print "\nokey!"; } sub test2{ print "\nokey!"; }
The above coding doesn't work. It is showing an error message.
Can't use string ("test") as a subroutine ref while "strict refs" in u +se at 1.p l line 4.

But, when I comment the line use strict; It is working well.

Can you leave your comments, why it is not working when I use use strict

Thank You,

Replies are listed 'Best First'.
Re: Error Message when I use Strict
by Zaxo (Archbishop) on Jul 29, 2005 at 08:32 UTC

    You are using a symbolic reference to a subroutine. That means that your reference is simply a variable containing the name of the sub, rather than a hard reference to the compiled code itself.

    The strict module always objects to soft references. You can recast your code to provide hard references, use a string as a key to a hash of code references (a dispatch table), or you can say no strict 'refs'; within a suitable small scope.

    After Compline,
    Zaxo

Re: Error Message when I use Strict
by holli (Abbot) on Jul 29, 2005 at 08:39 UTC
    another way to make this work under strict: Dispatch Tables.
    use strict; use warnings; my $SubroutName='test'; my %SubroutDispatch = ( test => \&test, test1 => \&test1, test2 => \&test2, ); my $text='abcdefgijkl'; my $sub = $SubroutDispatch{$SubroutName}; &$sub($text); sub test { print "\nokey $_[0]!"; } sub test1{ print "\nokey!"; } sub test2{ print "\nokey!"; }


    holli, /regexed monk/
      What does that buy you over:
      $SubroutName = 'test'; { no strict 'refs'; &$SubroutName; }
      There's not much danger in using symbolic references - what "use strict 'refs'" does for you is prevent you from using symbolic references accidentally (which can be a problem), but that isn't the case here. The biggest danger lies probably in mistyping the value for $SubroutName, which will lead to a run-type error. But your dispatch table suffers from that as well. The use of a symbolic reference to call a sub hardly differs from your solution - except that the dispatch table isn't coded explicitly - you're using the stash as the dispatch table.
        The biggest danger lies probably in mistyping the value for $SubroutName, which will lead to a run-type error.

        No, the biggest danger lies in accidentally calling another subroutine that you don't plan on calling there. This becomes especially dangerous if the subname is passed from the user (like from a CGI form). Using a dispatch table makes the possible calls explicit, which is usually a good thing.

        But your dispatch table suffers from that as well.
        my $sub = $SubroutDispatch{$SubroutName} || sub {return};


        holli, /regexed monk/
Re: Error Message when I use Strict
by Anonymous Monk on Jul 29, 2005 at 08:31 UTC
    If $SubroutName is a string, &$SubroutName is a symbolic reference - after all, you are using a string as if it were a reference. And using a symbolic reference is what strict 'refs' disallows.

    Either use no strict 'refs' around the call, use test(), or call it as a class method: main->$SubroutName is allowed, even with maximal strictness. But be aware that calling it as a class method implicitely passes the class as the first argument.

Re: Error Message when I use Strict
by MonkPaul (Friar) on Jul 29, 2005 at 17:04 UTC
    Can i first of all just ask why you are trying to pass arguments to a method this way.

    Im not sure if i have the whole picture here, maybe you have code afterwards for some special reason, BUT
    Can you not just call your subroutine the most obvious way using just the name and pass in the argument.

    use strict; my $text='abcdefgijkl'; test($text); sub test { print "\nokey!"; }

    I may have it wrong though.
    MonkPaul.