cannot acces variable inside while loop (in perl) - perl

A very easy question on variables scope. I have a variable defined in the main code that I use inside a while loop.
my $my_variable;
while(<FILE>) {
...using $my_variable
}
if ($my_variable) -> FAILS
When I exit the loop and use the variable I get an error:
Use of uninitialized value $my_variable
Even if I enclose the variable in a naked block I follow with the error.
{
my $my_variable;
while(<FILE>) {
...using $my_variable
}
if ($my_variable) -> FAILS
}
Any suggestion?

Are you using $my_variable in the loop or did you redefine it as my $my_variable somewhere in the loop. You'd be surprised how easily a my slips in to variable assignment.
I even have a frequent tick in my code where I write something like
my $hash{ $key } = ... some elaborate assignment;
Also, if should not complain about an uninitialized variable. undef => Boolean false.
I wouldn't worry about initializing all my variables -- but its crucial that you learn a mindset about how to use undefs. And always, always USUW (use strict; use warnings) so that variables aren't uninitialized when you don't expect them to be.

Do you ever assign to $my_variable? All you show is a declaration (the my) and a usage (the if) but never an assignment.

In the examples given, you didn't initialize $my_variable so it is undefined after the while loop.
You can do my $my_variable = ''; just before the loop.

Related

Is it possible to use hash, array, scalar with the same name in Perl?

I'm converting perl script to python.
I haven't used perl language before so many things in perl confused me.
For example, below, opt was declared as a scalar first but declared again as a hash. %opt = ();
Is it possible to declare a scalar and a hash with the same name in perl?
As I know, foreach $opt (#opts) means that scalar opt gets values of array opts one by one. opt is an array at this time???
In addition, what does $opt{$opt} mean?
opt outside $opt{$opt} is a hash and opt inside $opt{$opt} is a scalar?
I'm so confused, please help me ...
sub ParseOptions
{
local (#optval) = #_;
local ($opt, #opts, %valFollows, #newargs);
while (#optval) {
$opt = shift(#optval);
push(#opts,$opt);
$valFollows{$opt} = shift(#optval);
}
#optArgs = ();
%opt = ();
arg: while (defined($arg = shift(#ARGV))) {
foreach $opt (#opts) {
if ($arg eq $opt) {
push(#optArgs, $arg);
if ($valFollows{$opt}) {
if (#ARGV == 0) {
&Usage();
}
$opt{$opt} = shift(#ARGV);
push(#optArgs, $opt{$opt});
} else {
$opt{$opt} = 1;
}
next arg;
}
}
push(#newargs,$arg);
}
#ARGV = #newargs;
}
In Perl types SCALAR, ARRAY, and HASH are distinguished by the leading sigil in the variable name, $, #, and % respectively, but otherwise they may bear the same name. So $var and #var and %var are, other than belonging to the same *var typeglob, completely distinct variables.
A key for a hash must be a scalar, let's call it $key. A value in a hash must also be a scalar, and the one corresponding to $key in the hash %h is $h{$key}, the leading $ indicating that this is now a scalar. Much like an element of an array is a scalar, thus $ary[$index].
In foreach $var (#ary) the scalar $var does not really "get values" of array elements but rather aliases them. So if you change it in the loop you change the element of the array.
(Note, you have the array #opts, not #opt.)
A few comments on the code, in the light of common practices in modern Perl
One must always have use warnings; on top. The other one that is a must is use strict, as it enforces declaration of variables with my (or our), promoting all kinds of good behavior. This restricts the scope of lexical (my) variables to the nearest block enclosing the declaration
A declaration may be done inside loops as well, allowing while (my $var = EXPR) {} and foreach my $var (LIST) {}, and then $var is scoped to the loop's block (and is also usable in the rest of the condition)
The local is a different beast altogether, and in this code those should be my instead
Loop labels like arg: are commonly typed in block capitals
The & in front of a function name has rather particular meanings† and is rarely needed. It is almost certainly not needed in this code
Assignment of empty list like my #optArgs = () when the variable is declared (with my) is unneeded and has no effect (with a global #name it may be needed to clear it from higher scope)
In this code there is no need to introduce variables first since they are global and thus created the first time they are used, much like in Python – Unless they are used outside of this sub, in which case they may need to be cleared. That's the thing with globals, they radiate throughout all code
Except for the last two these are unrelated to your Python translation task, for this script.
† It suppresses prototypes; informs interpreter (at runtime) that it's a subroutine and not a "bareword", if it hasn't been already defined (can do that with () after the name); ensures that the user-defined sub is called, if there is a builtin of the same name; passes the caller's #_ (when without parens, &name); in goto &name and defined ...
See, for example, this post and this post
First, to make it clear, in perl, as in shell, you could surround variable names in curly brackets {} :
${bimbo} and $bimbo are the same scalar variable.
#bimbo is an array pointer ;
%bimbo is a hash pointer ;
$bimbo is a scalar (unique value).
To address an array or hash value, you will have to use the '$' :
$bimbo{'index'} is the 'index' value of hash %bimbo.
If $i contains an int, such as 1 for instance,
$bimbo[$i] is the second value of the array #bimbo.
So, as you can see, # or % ALWAYS refers to the whole array, as $bimbo{} or $bimbo[] refers to any value of the hash or array.
${bimbo[4]} refers to the 5th value of the array #bimbo ; %{bimbo{'index'}} refers to the 'index' value of array %bimbo.
Yes, all those structures could have the same name. This is one of the obvious syntax of perl.
And, euhm… always think in perl as a C++ edulcored syntax, it is simplified, but it is C.

Can someone explain why Perl behaves this way (variable scoping)?

My test goes like this:
use strict;
use warnings;
func();
my $string = 'string';
func();
sub func {
print $string, "\n";
}
And the result is:
Use of uninitialized value $string in print at test.pl line 10.
string
Perl allows us to call a function before it has been defined. However when the function uses a variable declared only after the function call, the variable appears to be undefined. Is this behavior documented somewhere? Thank you!
The behaviour of my is documented in perlsub - it boils down to this - perl knows $string is in scope - because the my tells it so.
The my operator declares the listed variables to be lexically confined to the enclosing block, conditional (if/unless/elsif/else), loop (for/foreach/while/until/continue), subroutine, eval, or do/require/use'd file.
It means it's 'in scope' from the point at which it's first 'seen' until the closing bracket of the current 'block'. (Or in your example - the end of the code)
However - in your example my also assigns a value.
This scoping process happens at compile time - where perl checks where it's valid to use $string or not. (Thanks to strict). However - it can't know what the value was, because that might change during code execution. (and is non-trivial to analyze)
So if you do this it might be a little clearer what's going on:
#!/usr/bin/env perl
use strict;
use warnings;
my $string; #undefined
func();
$string = 'string';
func();
sub func {
print $string, "\n";
}
$string is in scope in both cases - because the my happened at compile time - before the subroutine has been called - but it doesn't have a value set beyond the default of undef prior to the first invocation.
Note this contrasts with:
#!/usr/bin/env perl
use strict;
use warnings;
sub func {
print $string, "\n";
}
my $string; #undefined
func();
$string = 'string';
func();
Which errors because when the sub is declared, $string isn't in scope.
First of all, I would consider this undefined behaviour since it skips executing my like my $x if $cond; does.
That said, the behaviour is currently consistent and predictable. And in this instance, it behaves exactly as expected if the optimization that warranted the undefined behaviour notice didn't exit.
At compile-time, my has the effect of declaring and allocating the variable[1]. Scalars are initialized to undef when created. Arrays and hashes are created empty.
my $string was encountered by the compiler, so the variable was created. But since you haven't executed the assignment yet, it still has its default value (undefined) during the first call to func.
This model allows variables to be captured by closures.
Example 1:
{
my $x = "abc";
sub foo { $x } # Named subs capture at compile-time.
}
say foo(); # abc, even though $x fell out of scope before foo was called.
Example 2:
sub make_closure {
my ($x) = #_;
return sub { $x }; # Anon subs capture at run-time.
}
my $foo = make_closure("foo");
my $bar = make_closure("bar");
say $foo->(); # foo
say $bar->(); # bar
The allocation is possibly deferred until the variable is actually used.

Perl: what happens when we assign a constant value to a reference variable instead of address of a variable?

Example:
#! /usr/bin/perl -w
$$var=10;
print "Variable is containing $$var and is of type ". ref($$var)."\n";
Output:
$perl testRefVar.pl
Variable is containing 10 and is of type
Here the variable $$var is not referring to any other variable, but a constant. So is there any significance of prefixing a variable with '$$'?
This is the same as setting any other variable to 10, except that the access is indirect.
perl will autovivify an anonymous scalar variable and assign the reference to $var so that this action can be fulfilled. If you print out $var you will get something like SCALAR(0x3ecec4).
To do this explcitily you could write
my $temp;
my $var = \$temp;
$$var = 10;
which would assign 10 to the variable $temp.
If, instead, you set $var to a reference to a constant, like this
my $var = \99;
$$var = 10;
you would get the error message
Modification of a read-only value attempted
because in this case $var refers to a constant instead of a variable.
Here, $var is a a reference to a scalar, and $$var is the scalar itself. Unless your code specifically wants references, the indirection (requiring the use of two dollar signs when you want the actual scalar) is at the very least a cumbersome hassle.

Perl magic -- Is foreach variable by default locally defined and override outer value

I am expecting #arr1's last element as output from this code:
#!/usr/bin/perl
my #arr1 = qw(son kon bon won kon don pon won pon don won);
my $innr_element = '';
foreach $innr_element ( #arr1 ) {
## do something
}
print "--->$innr_element<---\n";
But I am getting nothing (blank output). If $innr_element is being created internally by Perl as block-scoped variable (inner to foreach) then below should work properly.
#!/usr/bin/perl
use strict;
my #arr1 = qw(son kon bon won kon don pon won pon don won);
#my $innr_element = '';
foreach $innr_element ( #arr1 ) {
##do something
}
print "--->$innr_element<---\n";
But above code return below error.
Global symbol "$innr_element" requires explicit package name at test.pl line 5.
Global symbol "$innr_element" requires explicit package name at test.pl line 8.
Execution of test.pl aborted due to compilation errors.
So its clear that Perl is not creating inner variable implicitly.
This document says the same. If you declare VAR with my, the scope of the variable will extend throughout the foreach statement, but not beyond it.
Is this another perl magic or I am missing something?
This is not described in much detail in the documentation, but here is what it says:
The foreach loop iterates over a normal list value and sets the variable VAR to be each element of the list in turn. If the variable is preceded with the keyword my, then it is lexically scoped, and is therefore visible only within the loop. Otherwise, the variable is implicitly local to the loop and regains its former value upon exiting the loop. If the variable was previously declared with my, it uses that variable instead of the global one, but it's still localized to the loop. This implicit localization occurs only in a foreach loop.
So, it is not magic, the variable is merely localized. Your example might look something like this:
my $innr_element='';
foreach local $innr_element ( #arr1 ) {
...

How does the closure mechanism work in Perl?

Newbie in Perl again here, trying to understand closure in Perl.
So here's an example of code which I don't understand:
sub make_saying {
my $salute = shift;
my $newfunc = sub {
my $target = shift;
print "$salute, $target!\n";
};
return $newfunc; # Return a closure
}
$f = make_saying("Howdy"); # Create a closure
$g = make_saying("Greetings"); # Create another closure
# Time passes...
$f->("world");
$g->("earthlings");
So my questions are:
If a variable is assigned to a function, is it automatically a reference to that function?
In that above code, can I write $f = \make_saying("Howdy") instead? And when can I use the & because I tried using that in passing the parameters (&$f("world")) but it doesn't work.
and lastly, in that code above how did the strings world and earthlings get appended to the strings Howdy and Greetings.
Note: I understand that $f is somewhat bound to the function with the parameter "Howdy" so that's my understanding how "world" got appended. What I don't understand is the 2nd function inside. How that one operates its magic. Sorry I really don't know how to ask this one.
In Perl, scalar variables cannot hold subroutines directly, they can only hold references. This is very much like scalars cannot hold arrays or hashes, only arrayrefs or hashrefs.
The sub { ... } evaluates to a coderef, so you can directly assign it to a scalar variable. If you want to assign a named function (e.g. foo), you have to obtain the reference like \&foo.
You can call coderefs like $code->(#args) or &$code(#args).
The code
$f = \make_saying("Howdy")
evaluates make_saying("Howdy"), and takes a reference to the returned value. So you get a reference that points to a coderef, not a coderef itself.
Therefore, it can't be called like &$f("world"), you need to dereference one extra level: &$$f("world").
A closure is a function that is bound to a certain environment.
The environment consists of all currently visible variables, so a closure always remembers that scope. In the code
my $x;
sub foo {
my $y;
return sub { "$x, $y" };
}
foo is a closure over $x, as the outer environment consists of $x. The inner sub is a closure over $x and $y.
Each time foo is executed, we get a new $y and therefore a new closure. Most importantly $y does not "go out of scope" when foo is left, but it will be "kept alive" as it's still reachable from the closure returned.
In short: $y is a "local state" of the closure returned.
When we execute make_saying("Howdy"), the $salute variable is set to Howdy. The returned closure remembers that scope.
When we execute it again with make_saying("Greetings"), the body of make_saying is evaluated again. The $salute is now set to Greetings, and the inner sub closes over this variable. This variable is separate from the previous $salute, which still exists, but isn't accessible except through the first closure.
The two greeters have closed over separate $salute variables. When they are executed, their respective $salute is still in scope, and they can access and modify the value.
If a variable is asigned to a function, is it automatically a
reference to that function?
No. In example the function make_saying return reference another function. Such closures do not have name and can catch a variable from outside its scope (variable $salute in your example).
In that above code, can i write $f = \make_saying("Howdy") instead?
And when can i use the & cause i tried using that in passing the
parameters (&$f("world")) but it doesnt work.
No. $f = \make_saying("Howdy") is not what you think (read amon post for details). You can write $f = \&make_saying; which means "put into $f reference to function make_saying". You can use it later like this:
my $f = \&make_saying;
my $other_f = $f->("Howdy");
$other_f->("world");
and lastly, In that code above how in he** did the words world and
earthlings got appended to the words howdy and greetings.
make_saying creating my variable which goes into lamda (my $newfunc = sub); that lambda is returned from make_saying. It holds the given word "Howdy" through "closing" (? sorry dont know which word in english).
Every time you call the subroutine 'make_saying', it:
creates a DIFFERENT closure
assigns the received parameter to the scalar '$salute'
defines (creates but not execute) an inner anonymous subroutine:
That is the reason why at that moment nothing is assigned to the scalar
$target nor is the statement print "$salute, $target!\n"; executed .
finally the subroutine 'make_saying' returns a reference to the inner anonymous subroutine, that reference becomes the only way to call the (specific) anonymous subroutine.
Ever time you call each anonymous subroutine, it:
assign the received parameter to the scalar $target
sees also the scalar $salute that will have the value assigned at the moment in which was created the anonymous subroutine (when was called its parent subroutine make_saying
finally executes the statement print "$salute, $target!\n";