Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

using strict

by NovMonk (Chaplain)
on Mar 22, 2004 at 20:46 UTC ( #338761=perlquestion: print w/replies, xml ) Need Help??
NovMonk has asked for the wisdom of the Perl Monks concerning the following question:

Greetings, Monks.

I have been converted to "use strict, warnings, etc." (Wait, hold your applause....) I've read many of the FAQ's and nodes on the subject, and even found where they buried the initial discussion of "strict" on page 31 of my battered copy of Perl by Example (And they never mention it again in said examples, for all I can tell.)

Here's my remaining confusion-- it looks as if you can declare a variable as you assign it a value, thus:

 my $a = 5;

But, I'm assigning several variables at once to the results of a split, and "strict" is not happy with it until I declare them all at the top of the program thus:

 my ($a, $b, $c);

Here's my script prior to adding the my line declaring everything at the top -- what am I missing, or what should I go back and read a few more times?

#!/usr/bin/perl use strict; use warnings; open (IN, "infile") or die "Can't open input file: $!\n"; open (OUT, ">outfile") or die "Can't create outfile for write: $!\n "; while (<IN>) { if (/^##recstart/) { my ($junk,$recno) = split; $recno =~ s/'//g; } elsif (/^##v/) { my ($junk,$qno,$junk2,$vtext) = split (/ /,$_,4); $qno =~ s/'//g; $vtext =~ s/'//g; } else { print OUT "$recno^$qno^$vtext"; } }

Running this program as it is gives me the error:

Global symbol "$recno" requires explicit package name at verb.pl line +18. Global symbol "$qno" requires explicit package name at verb.pl line 18 +. Global symbol "$vtext" requires explicit package name at verb.pl line +18. Execution of verb.pl aborted due to compilation errors.

I don't know why it likes the first my ($junk, $recno); line but not the second.

Thanks for gentle enlightenment. If I can't get that, the other is fine too ;-).

Pax,

NovMonk

Replies are listed 'Best First'.
Re: using strict
by Fletch (Chancellor) on Mar 22, 2004 at 20:56 UTC

    Your declarations are lexical in scope and vanish at the end of the enclosing block. Since your my declarations take place in two different blocks and you then try to access them in a third they're no longer valid. You need to declare them in the largest enclosing scope (in this case you'd want to do so at the top of the while loop outside all branches of your conditional).

    On an unrelated note, using undef rather than a junk variable is better practice if you don't need one of the return values from split (or wrap the split in parens and subscript it to pull out what you want, e.g. ( $foo, $bar ) = ( split( /:/ ) )[1,4]).

Re: using strict
by tcf22 (Priest) on Mar 22, 2004 at 20:56 UTC
    It is because you are using "$recno^$qno^$vtext"; in your print statement, but they aren't declared in the block.

    For Example:
    my $a = <STDIN>; if($a eq 'y'){ my ($fname, $lname) = ('tom', 'test'); print "$fname $lname\n"; #OK because vars declared in block } print "$fname $lname\n"; #Vars are out of scope now, will die under st +rict


    Your code should look something like this, so your vars can be used between loop iterations.
    #!/usr/bin/perl use strict; use warnings; open (IN, "infile") or die "Can't open input file: $!\n"; open (OUT, ">outfile") or die "Can't create outfile for write: $!\n "; my ($junk,$qno,$junk2,$vtext,$recno); while (<IN>) { if (/^##recstart/) { ($junk,$recno) = split; $recno =~ s/'//g; }elsif (/^##v/) { ($junk,$qno,$junk2,$vtext) = split (/ /,$_,4); $qno =~ s/'//g; $vtext =~ s/'//g; }else { print OUT "$recno^$qno^$vtext"; } }

    - Tom

Re: using strict
by chip (Curate) on Mar 22, 2004 at 20:57 UTC
    Those my declarations are only effective to the end of the enclosing block .. i.e. the one if/else clause in which each one appears.

    Moving them up to the top of the while block should suffice.

        -- Chip Salzenberg, Free-Floating Agent of Chaos

Re: using strict
by muba (Priest) on Mar 22, 2004 at 20:56 UTC
    It has all to do with scoping. my declares a variable for the current scope. Basicly, a scope is a part of code between { and }. Or at least, that is how I understand it. Please, monks, correct me if I'm wrong.

    But, with this information, it's pretty clear why your code is not working:
    ... if (/^##recstart/) { my ($junk,$recno) = split; # $recno declared for this block $recno =~ s/'//g; } elsif (/^##v/) { my ($junk,$qno,$junk2,$vtext) = split (/ /,$_,4); # both $qno and $vtext declared for this block $qno =~ s/'//g; $vtext =~ s/'//g; } else { # nothing declared at all for this else block print OUT "$recno^$qno^$vtext"; } }
Re: using strict
by tinita (Parson) on Mar 22, 2004 at 21:02 UTC
    i can recommend using perlsub, "Private Variables via my()".
    just quoting from there:

    The "my" operator declares the listed variables to be lex-
    ically confined to the enclosing block, conditional
    ("if/unless/elsif/else"), loop ("for/fore-
    ach/while/until/continue"), subroutine, "eval", or
    "do/require/use"'d file.

    you're doing something like

    # scope file if ($condition1) { # scope if my $inner = 1; } else { # scope else my $inner = 2; } # scope file print $inner;
    but $inner is only seen in "scope if" and "scope else". no variable $inner has ever been defined in "scope file". so just add a my $inner; before your if/else-stataments.
    additionally your logic doesn't make sense to me. you say, if condition1, set the variables to something, if condition2, set them to something else, and otherwise don't set them, but print them. but if they aren't set the print seems pretty useless and will issue a warning.
    there are also fine tutorials here in the tutorials section about my(), strict etc. where you might find answers.
Re: using strict
by NovMonk (Chaplain) on Mar 23, 2004 at 14:35 UTC
    Thanks for the replies, everyone. ++ to all. I now see that you Can declare variables in a line like this  my ($a, $b, $c) = split; but Only if you use the variables so declared within that block. So my original solution was correct (declare everything up front) but not for the reason I was confused about.

    Thanks especially to fletch for this gem of elightenment:

    On an unrelated note, using undef rather than a junk variable is better practice if you don't need one of the return values from split (or wrap the split in parens and subscript it to pull out what you want, e.g. ( $foo, $bar ) = ( split( /:/ ) )[1,4]).

    I'll go read some more tutorials now. Thanks again.

    NovMonk

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://338761]
Approved by Corion
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (4)
As of 2018-02-20 02:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    When it is dark outside I am happiest to see ...














    Results (266 votes). Check out past polls.

    Notices?