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

Dear Monks,

I am currently creating a script which will run on windows computer.
This script will test a lot of the system settings.

Tests will be often added or removed.

If I try to use the code below, I got the following message: "Can't use string ("test1") as a subroutine ref while "strict refs" in use at testlist.pl line 10."

I understand the error message, but what should be the best and easy way to avoid this situation? (I can ommit the "use strict", but it is not the way I want to do it)

use strict; use warnings; my @testlist=('test1','test2'); foreach (@testlist) { print ("dear user test $_ is currently running\n"); #call test &$_(); } sub test1 { #test1 code print "test1...done\n"; } sub test2 { #test2 code print "test2...done\n"; }

Thanks in advance

Replies are listed 'Best First'.
Re: strict refs usage
by GrandFather (Saint) on Sep 22, 2005 at 10:04 UTC

    Use references instead:

    use strict; use warnings; my @testlist=(\&test1, \&test2); foreach (@testlist) { #call test $_->(); } sub test1 { print ("dear user test1 is currently running\n"); #test1 code print "test1...done\n"; } sub test2 { print ("dear user test2 is currently running\n"); #test2 code print "test2...done\n"; }

    Perl is Huffman encoded by design.
      I finally used this method, it fit the way I want to run/add/remove my tests.

      Thanks for all your replies
Re: strict refs usage
by VSarkiss (Monsignor) on Sep 22, 2005 at 14:05 UTC
Re: strict refs usage
by Anonymous Monk on Sep 22, 2005 at 09:59 UTC
    That depends on what you want to do. If you want to use names of subroutines in a list, and use the names to call the subs, you will be using symbolic references - which will not be permitted with 'use strict "refs"'. So, you're only option is to turn of 'use strict "refs"' when performing this call. And there's nothing wrong with that. 'use strict "refs"' prevents you from accidently using symbolic references - but here, you are doing it on purpose.

    Another way of handling this situation is to use the line

    my @testlist = (\&test1, \&test2);
    This gives you actual code references. However, I realize your program is just a mockup - and in your real program the list of names might come from somewhere else, and can't be replaced with a list of code references.
Re: strict refs usage
by splinky (Hermit) on Sep 22, 2005 at 15:47 UTC
    Everybody's told you all the reasons why you shouldn't do this, and given you all kinds of good alternatives. If, however, you really really have to do it this way, you can simply do the following to call the tests:
    { no strict 'refs'; &$_(); }
    This will turn strict refs off for only the one statement and leave it on everywhere else.
Re: strict refs usage
by chromatic (Archbishop) on Sep 22, 2005 at 16:40 UTC
    for my $test ( qw( test1 test2 )) { next unless my $test_sub = main->can( $test ); print "Dear user, test $test is currently running.\n"; $test_sub->(); }
      Isn't this just a sneaky^Wintelligent way to use symbolic references? ;)

      -QM
      --
      Quantum Mechanics: The dreams stuff is made of

        Certainly you're still looking up a symbol name in a symbol table, but this is what Perl does internally when you call a subroutine anyway. No, knowing the name of the subroutine at compile-time doesn't allow any real optimization here.

        At least this approach gives a bit more safety over calling the symbolic reference directly.

Re: strict refs usage
by Tanktalus (Canon) on Sep 22, 2005 at 14:47 UTC

    If you're reasonably comfortable with OO, another way to do it is by separating each test out into its own module, instantiating each module as an object, and then calling $obj->run_test() on each. This is actually very similar to my post on Tasks and TaskManagers which I expanded upon a bit in another post the same day.

    I use this paradigm to set up tasks which I can really easily mix and match. I can easily whip up a script that calls different sets of tasks - a common example is where I want to call a subset of tasks from my main script so I can just test those tasks. By making each task as independant from one another as is reasonably possible, this becomes really quite trivial.

Re: strict refs usage
by tphyahoo (Vicar) on Sep 24, 2005 at 11:03 UTC
    I like using my $var = {#code} in these types of situations.
    use strict; use warnings; my $test1 = sub { print "test1...done\n"; }; my $test2 = sub { print "test2...done\n"; }; my $testlist = { 1=>$test1, 2=>$test2 }; foreach (keys %$testlist) { print ("dear user test $_ is currently running\n"); $testlist->{$_}(); }