Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Declaring Variables

by Stamp_Guy (Monk)
on Feb 28, 2001 at 07:21 UTC ( [id://61271]=perlquestion: print w/replies, xml ) Need Help??

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

Hey guys, Say I have a variable that I want a subroutine to set:
if ($myvariable=~/myregex/) { $this_variable="1"; } else { $this_variable="0"; }
Or something like that. When I use strict, I am told that I have to predeclare the variable. When I use my on it, I am unable to use it anywhere else. Are there any obvious ways around this that you know of? I understand why it works this way, I'm just frustrated because I can't figure out how to get around it.

Replies are listed 'Best First'.
Re: Declaring Variables
by Adam (Vicar) on Feb 28, 2001 at 07:24 UTC
    With a simple clause I do:
    my $var = ( $test =~ m/regex/ ) ? "true value" : "false value";
    With more complex clauses, or multiple variables on one clause, I predeclare:
    my $var1; my $var2; if( $clause ) { $var1 = "blah"; $var2 = "deblah"; } else { $var1 = "foo"; $var2 = "bar"; }
    As for getting variables out of subroutines, either have the routine return the variable, or pass the variable into the subroutine. Either way, scope the variable in the namespace where you want to use it, and if you are setting it else where, then pass it around.
Re (tilly) 1: Declaring Variables
by tilly (Archbishop) on Feb 28, 2001 at 07:34 UTC
    That is what the vars module is for.

    That said, only rarely is it a good design to have subroutines whose job is to communicate by setting global variables...

Re: Declaring Variables
by dvergin (Monsignor) on Feb 28, 2001 at 13:46 UTC
    Here is some fairly verbose, plain-vanilla code that illustrates some of the points made in the posts above. The general recommendation being that you avoid using variables floating around in global space. Rather, feed the values you need explicitly to and from the subroutine. This discipline will help you a lot as your programs get larger and more complex.
    #!/usr/bin/perl5 -w use strict; my ($is_okay, $value); sub return_okay { my $test_string = shift; my $private_result = ($test_string =~ /myregex/); return ($private_result); } sub return_okay2 { # concise version return ($_[0] =~ /myregex/); } sub modify_okay { # but see WARNING below # Called as: modify_okay($string, $result_flag) $_[1] = ($_[0] =~ /myregex/); } my @vals = qw(abcdefg myregex tuvwxyz); print "Using a return value:\n"; foreach $value (@vals) { $is_okay = return_okay2($value); ### if ($is_okay) { print "$value is okay.\n"; } else { print "$value is not okay.\n"; } } print "\nUsing a modified value:\n"; foreach $value (@vals) { modify_okay($value, $is_okay); ### if ($is_okay) { print "$value is okay.\n"; } else { print "$value is not okay.\n"; } } # WARNING: the modify method can blow up on you # Notice that the following line causes a fatal error # because of the attempt to modify a constant: modify_okay("some string", 1); print "And this never prints\n";
    Is there a chance you will forget at some point and pass the modify version a constant? We've all done it. So will you.

    Use return values. They don't choke trying to modify constants and (bonus) they are more clear. You have to look twice at the call to modify_okay() to figure out that the first variable is input but the second variable is being modified behind your back.

    P.S. The above was intentionally verbose. With a little jiggering, the foreach loops can be condensed to:

    for (@vals) { my $qualifier = return_okay2($_) ? "" : " not"; print "$_ is$qualifier okay.\n"; }
    or... print map "$_ is ".(return_okay2($_)?'':' not')." okay\n", @vals; Which really doesn't relate to your question, but is fun anyway!
Re: Declaring Variables
by perlmonkey (Hermit) on Feb 28, 2001 at 07:50 UTC
    I am NOT suggesting this, but I thought I would chime in. You can modify the stack paramaters directly:
    use strict; sub test { if( $_[0] =~ /regex/ ) { $_[1] = "match"; } else { $_[1] = "no match"; } } my $bool; test( "foo", $bool ); print "foo: $bool\n"; test( "regex", $bool ); print "regex: $bool\n";
    That is just silly though. Use the 'vars' method mentioned above or just have your subs return a value instead of setting a global variable if that is possible.

    You can also encapsulate a my'd variable and make it semi global via subroutine calls, but this is sort of silly also:
    use strict; { my $foo; sub setFoo{ $foo = shift; } sub getFoo{ return $foo; } }
Re: Declaring Variables
by cleen (Pilgrim) on Feb 28, 2001 at 07:40 UTC
    put the my $this-variable statement somewhere outside the loop or subroutine where you want other parts to get info from it.
    my $myvariable; my $this-variable; $this-variable = 1 if $myvariable =~ /blah/;
    then later on in the code you can do this
    print "HEY!\n" if $this-variable; print "NO!\n" if !$this-variable;

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (4)
As of 2024-04-20 15:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found