Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

How to sovle this, if i use strict i'm getting error.

by sen (Hermit)
on Dec 06, 2005 at 07:07 UTC ( #514350=perlquestion: print w/ replies, xml ) Need Help??
sen has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks,

The below code is working, if i use pragma 'use strict' i am getting error in my code..

Please help me Thanks in Advance..

Error : Can't use string ("test1") as a subroutine ref while "strict refs" in use at new.pl line 5

#!/usr/local/bin/perl for(my $i=1; $i<=2; $i++) { $a = 'test'.$i; &$a; } sub test1 { print 'test1'; } sub test2 { print 'test2'; }

Comment on How to sovle this, if i use strict i'm getting error.
Select or Download Code
Re: How to sovle this, if i use strict i'm getting error.
by Samy_rio (Vicar) on Dec 06, 2005 at 07:15 UTC

    Hi sen, Try this,

    #!/usr/local/bin/perl use strict; for(my $i=1; $i<=2; $i++) { my $a = 'test'.$i; eval "&$a"; } sub test1 { print 'test1'; } sub test2 { print 'test2'; }

    Regards,
    Velusamy R.


    eval"print uc\"\\c$_\""for split'','j)@,/6%@0%2,`e@3!-9v2)/@|6%,53!-9@2~j';

      To sum up all that has been said, especially the warning re avoiding symrefs if possible, and here it is not only possible but also highly recommendable, so I'm stressing the point once more:
      #!/usr/bin/perl -l use strict; use warnings; my %dispatch=( test1 => sub { print 'test1'; }, test2 => sub { print 'test2'; } ); for(1,2) { $dispatch{"test$_"}->(); } __END__
      Notice that I also used -> rather than & for dereferencing, which is preferrable for various reasons, and a (more) perlish for loop, which could have also been a modifier:
      $dispatch{"test$_"}->() for 1,2;
      But then, if you just need a few numbered subs, depending on your actual application, you may prefer an array instead:
      #!/usr/bin/perl -l use strict; use warnings; my @test=( sub { print 'test0' }, sub { print 'test1' } ); $test[$_]->() for 0,1; # or even $_->() for @test; __END__
Re: How to sovle this, if i use strict i'm getting error.
by gube (Parson) on Dec 06, 2005 at 07:16 UTC

    Hi sen, put eval "&$a"; and run the code than it will works..

    Refer perldoc -f eval

Re: How to sovle this, if i use strict i'm getting error.
by Corion (Pope) on Dec 06, 2005 at 07:22 UTC

    Using a string as a subroutine name is almost always a bad idea. What you want instead is a "dispatch table", that is, a hash that maps your names to subroutines:

    #!/usr/local/bin/perl -w use strict; sub test1 { print 'test1'; } sub test2 { print 'test2'; } for my $i (1,2) { my $name = "test$i"; if (exists $handler{$name}) { $handler{$name}->(); } else { warn "Don't know what to do with '$name'"; }; }; my %handler = ( test1 => \&test1, test2 => \&test2, );

    This method allows you to extend your program while also giving you good error handling in the case that you want to call something by name which doesn't exist. It also makes your program more secure because only things can be called that you have specified as callable.

      I suppose I'm nitpicking here, but something has always bothered me about this answer (and those like it). Perl already provides a perfectly code "dispatch table", that is, a hash that maps subroutine names to subroutine references! I'm not sure why people are so strongly discouarged from using it. It's one thing to discourage accessing this hash for variables, since that leads to global variables and other such evil, but in this case you're just wasting effort to create something that already exists.

        The point is control. Eval-based dispatch is much like an unstructured goto $EXPR - you cannot really be sure of the program flow. An explicit hash lists all locations where the code is allowed to branch to. This prevents malicious attacks where the attacker could try to make a call to the exit or system core function and it allows much better error handling. It also decouples the subroutine name from the argument, which I find very convenient in web applications.

        They think it's a bad idea because 'use strict' complains ... but if you know that what you're trying to do is correct, you can shut off 'use strict' for the specific complaint that it has:

        use strict; use warnings; for my $i ( 1 .. 2 ) { $a = 'test'.$i; no strict 'refs'; &$a; } sub test1 { print 'test1'; } sub test2 { print 'test2'; }

        So where's the problem with that? None, really. I mean, it doesn't propogate, so you're still protected in the subroutine you're calling:

        use strict; use warnings; for my $a qw( test1 test2 ) { no strict 'refs'; &$a; } sub test1 { print 'test1'; } sub test2 { my $x='test3'; &$x }

        PS. For the original poster -- it's convention that you don't use $a and $b as variable names, unless you're dealing with sorting.

Re: How to sovle this, if i use strict i'm getting error.
by gopalr (Priest) on Dec 06, 2005 at 08:42 UTC

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://514350]
Approved by gube
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (13)
As of 2014-09-16 15:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (33 votes), past polls