Why can't I declare a scalar variable inside an if statement? Does it have something to do with the scope of the variable?
Every block {...} in Perl creates a new scope. This includes bare blocks, subroutine blocks, BEGIN blocks, control structure blocks, looping structure blocks, inline blocks (map/grep), eval blocks, and the bodies of statement modifier loops.
If a block has an initialization section, that section is considered within the scope of the following block.
if (my $x = some_sub()) {
# $x in scope here
}
# $x out of scope
In a statement modifier loop, the initialization section is not contained within the scope of the pseudo block:
$_ = 1 for my ($x, $y, $z);
# $x, $y, and $z are still in scope and each is set to 1
Who says you can't?
#! /usr/bin/env perl
use warnings;
no warnings qw(uninitialized);
use strict;
use feature qw(say);
use Data::Dumper;
my $bar;
if (my $foo eq $bar) {
say "\$foo and \$bar match";
}
else {
say "Something freaky happened";
}
$ ./test.pl
$foo and $bar match
Works perfectly! Of course it makes no sense since what are you comparing $foo too? It has no value.
Can you give me an example of what you're doing and the results you're getting?
Or, is this more what you mean?:
if (1 == 1) {
my $foo = "bar";
say "$foo"; #Okay, $foo is in scope
}
say "$foo;" #Fail: $foo doesn't exist because it's out of scope
So, which one do you mean?
Just to follow up my comment. Statements such as the following is perfectly legal:
if( my( $foo, $bar ) = $baz =~ /^(.*?)=(.*?)$/ ) {
# Do stuff
}
Courtesy of one of my colleagues.
There's an exception: You may not conditionally declare a variable and use it under different conditions. This means the following isn't allowed:
my $x = ... if ...;
Related
I wrote a script in perl which does multi-threading, I then tried to convert it over into an object. However, I can't seem to figure out how to lock on a member variable. The closest I've come to is:
#!/usr/bin/perl
package Y;
use warnings;
use strict;
use threads;
use threads::shared;
sub new
{
my $class = shift;
my $val :shared = 0;
my $self =
{
x => \$val
};
bless $self, $class;
is_shared($self->{x}) or die "nope";
return $self;
}
package MAIN;
use warnings;
use strict;
use threads;
use threads::shared;
use Data::Dumper;
my $x = new Y();
{
lock($x->{x});
}
print Dumper('0'); # prints: $VAR = '0';
print Dumper($x->{x}); # prints: $VAR = \'0';
print "yes\n" if ($x->{x} == 0); # prints nothing
#print "yes\n" if ($$x->{x} == 0); # dies with msg: Not a SCALAR reference
my $tmp = $x->{x}; # this works. Must be a order of precedence thing.
print "yes\n" if ($$tmp == 0); # prints: yes
#++$$x->{x}; # dies with msg: Not a SCALAR reference
++$$tmp;
print Dumper($x->{x}); # prints: $VAR = \'1';
This allows me to put a lock on the member var x, but it means I'd be needing 2 member variables as the actual member var isn't really capable of being manipulated by assigning to it, incrementing it, etc. I can't even test against it.
EDIT:
I'm thinking that I should rename this question "How do you dereference a member variable in perl?" as the problem seems to boil down to that. Using $$x->{x} is invalid syntax and you can't force precedence rules with parentheses. I.e. $($x->{x}) doesn't work. Using a temporary works but it a nuisance.
I don't get what you are trying to do with threads and locking, but there are some simple errors in the way you use references.
$x->{x}
is a reference to a scalar, so the expressions
$x->{x} == 0
++$$x->{x}
both look suspect. $$x->{x} is parsed as {$$x}->{x} (dereference $x, then treat it as a hash reference and look up the value with key x). I think you mean to say
${$x->{x}} == 0
++${$x->{x}}
where ${$x->{x}} means to treat $x as a hash reference, to look up the value for key x in that hash, and then to dererence that value.
(sub {
print 1;
})();
sub {
print 1;
}();
I tried various ways, all are wrong...
(sub { ... }) will give you the pointer to the function so you must call by reference.
(sub { print "Hello world\n" })->();
The other easy method, as pointed out by Blagovest Buyukliev would be to dereference the function pointer and call that using the { } operators
&{ sub { print "Hello World" }}();
Yay, I didn't expect you folks to come up with that much possibilities. But you're right, this is perl and TIMTOWTDI: +1 for creativitiy!
But to be honest, I use hardly another form than the following:
The Basic Syntax
my $greet = sub {
my ( $name ) = #_;
print "Hello $name\n";
};
# ...
$greet->( 'asker' )
It's pretty straight forward: sub {} returns a reference to a sub routine, which you can store and pass around like any other scalar. You can than call it by dereferencing. There is also a second syntax to dereference: &{ $sub }( 'asker' ), but I personally prefer the arrow syntax, because I find it more readable and it pretty much aligns with dereferencing hashes $hash->{ $key } and arrays $array->[ $index ]. More information on references can be found in perldoc perlref.
I think the other given examples are a bit advanced, but why not have a look at them:
Goto
sub bar {goto $foo};
bar;
Rarely seen and much feared these days. But at least it's a goto &function, which is considered less harmful than it's crooked friends: goto LABEL or goto EXPRESSION ( they are deprecated since 5.12 and raise a warning ). There are actually some circumstances, when you want to use that form, because this is not a usual function call. The calling function ( bar in the given example ) will not appear in the callling stack. And you don't pass your parameters, but the current #_ will be used. Have a look at this:
use Carp qw( cluck );
my $cluck = sub {
my ( $message ) = #_;
cluck $message . "\n";
};
sub invisible {
#_ = ( 'fake' );
goto $cluck;
}
invisible( 'real' );
Output:
fake at bar.pl line 5
main::__ANON__('fake') called at bar.pl line 14
And there is no hint of an invisible function in the stack trace. More info on goto in perldoc -f goto.
Method Calls
''->$foo;
# or
undef->$foo;
If you call a method on an object, the first parameter passed to that method will be the invocant ( usually an instance or the class name ). Did i already say that TIMTOWTCallAFunction?
# this is just a normal named sub
sub ask {
my ( $name, $question ) = #_;
print "$question, $name?\n";
};
my $ask = \&ask; # lets take a reference to that sub
my $question = "What's up";
'asker'->ask( $question ); # 1: doesn't work
my $meth_name = 'ask';
'asker'->$meth_name( $question ); # 2: doesn't work either
'asker'->$ask( $question ); # 1: this works
In the snippet above are two calls, which won't work, because perl will try to find a method called ask in package asker ( actually it would work if that code was in the said package ). But the third one succeeds, because you already give perl the right method and it doesn't need to search for it. As always: more info in the perldoc I can't find any reason right now, to excuse this in production code.
Conclusion
Originally I didn't intend to write that much, but I think it's important to have the common solution at the beginning of an answer and some explanations to the unusual constructs. I admit to be kind of selfish here: Every one of us could end up maintaining someones code, who found this question and just copied the topmost example.
There is not much need in Perl to call an anonymous subroutine where it is defined. In general you can achieve any type of scoping you need with bare blocks. The one use case that comes to mind is to create an aliased array:
my $alias = sub {\#_}->(my ($x, $y, $z));
$x = $z = 0;
$y = 1;
print "#$alias"; # '0 1 0'
Otherwise, you would usually store an anonymous subroutine in a variable or data structure. The following calling styles work with both a variable and a sub {...} declaration:
dereference arrow: sub {...}->(args) or $code->(args)
dereference sigil: &{sub {...}}(args) or &$code(args)
if you have the coderef in a scalar, you can also use it as a method on regular and blessed values.
my $method = sub {...};
$obj->$method # same as $method->($obj)
$obj->$method(...) # $method->($obj, ...)
[1, 2, 3]->$method # $method->([1, 2, 3])
[1, 2, 3]->$method(...) # $method->([1, 2, 3], ...)
I'm endlessly amused by finding ways to call anonymous functions:
$foo = sub {say 1};
sub bar {goto $foo};
bar;
''->$foo; # technically a method, along with the lovely:
undef->$foo;
() = sort $foo 1,1; # if you have only two arguments
and, of course, the obvious:
&$foo();
$foo->();
You need arrow operator:
(sub { print 1;})->();
You might not even need an anonymous function if you want to run a block of code and there is zero or one input. You can use map instead.
Just for the side effect:
map { print 1 } 1;
Transform data, take care to assign to a list:
my ($data) = map { $_ * $_ } 2;
# ------------------------------------------------------
# perl: filter array using given function
# ------------------------------------------------------
sub filter {
my ($arr1, $func) = #_;
my #arr2=();
foreach ( #{$arr1} ) {
push ( #arr2, $_ ) if $func->( $_ );
};
return #arr2;
}
# ------------------------------------------------------
# get files from dir
# ------------------------------------------------------
sub getFiles{
my ($p) = #_;
opendir my $dir, $p or die "Cannot open directory: $!";
my #files=readdir $dir;
closedir $dir;
#return files and directories that not ignored but not links
return filter \#files, (sub { my $f = $p.(shift);return ((-f $f) || (-d $f)) && (! -l $f) } );
}
the following code
#!/usr/bin/env perl
use strict;
use warnings;
my #foo = (0,1,2,3,4);
foreach my $i (#foo) {
sub printer {
my $blah = shift #_;
print "$blah-$i\n";
}
printer("test");
}
does not do what I would expect.
What exactly is happening?
(I would expect it to print out "test-0\ntest-1\ntest-2\ntest-3\ntest-4\n")
The problem is that the sub name {...} construct can not be nested like that in a for loop.
The reason is because sub name {...} really means BEGIN {*name = sub {...}} and begin blocks are executed as soon as they are parsed. So the compilation and variable binding of the subroutine happens at compile time, before the for loop ever gets a chance to run.
What you want to do is to create an anonymous subroutine, which will bind its variables at runtime:
#!/usr/bin/env perl
use strict;
use warnings;
my #foo = (0,1,2,3,4);
foreach my $i (#foo) {
my $printer = sub {
my $blah = shift #_;
print "$blah-$i\n";
};
$printer->("test");
}
which prints
test-0
test-1
test-2
test-3
test-4
Presumably in your real use case, these closures will be loaded into an array or hash so that they can be accessed later.
You can still use bareword identifiers with closures, but you need to do a little extra work to make sure the names are visible at compile time:
BEGIN {
for my $color (qw(red blue green)) {
no strict 'refs';
*$color = sub {"<font color='$color'>#_</font>"}
}
}
print "Throw the ", red 'ball'; # "Throw the <font color='red'>ball</font>"
Eric Strom's answer is correct, and probably what you wanted to see, but doesn't go into the details of the binding.
A brief note about lexical lifespan: lexicals are created at compile time and are actually available even before their scope is entered, as this example shows:
my $i;
BEGIN { $i = 42 }
print $i;
Thereafter, when they go out of scope, they become unavailable until the next time they are in scope:
print i();
{
my $i;
BEGIN { $i = 42 }
# in the scope of `my $i`, but doesn't actually
# refer to $i, so not a closure over it:
sub i { eval '$i' }
}
print i();
In your code, the closure is bound to the initial lexical $i at compile time.
However, foreach loops are a little odd; while the my $i actually creates a lexical, the foreach loop does not use it; instead it aliases it to one of the looped over values each iteration and then restores it to its original state after the loop. Your closure thus is the only thing referencing the original lexical $i.
A slight variation shows more complexity:
foreach (#foo) {
my $i = $_;
sub printer {
my $blah = shift #_;
print "$blah-$i\n";
}
printer("test");
}
Here, the original $i is created at compile time and the closure binds to that; the first iteration of the loop sets it, but the second iteration of the loop creates a new $i unassociated with the closure.
Consider the following Perl code.
#!/usr/bin/perl
use strict;
use warnings;
$b="1";
my $a="${b}";
$b="2";
print $a;
The script obviously outputs 1. I would like it to be whatever the current value of $b is.
What would be the smartest way in Perl to achieve lazy evaluation like this? I would like the ${b} to remain "unreplaced" until $a is needed.
I'm more interested in knowing why you want to do this. You could use a variety of approaches depending on what you really need to do.
You could wrap up the code in a coderef, and only evaluate it when you need it:
use strict; use warnings;
my $b = '1';
my $a = sub { $b };
$b = '2';
print $a->();
A variant of this would be to use a named function as a closure (this is probably the best approach, in the larger context of your calling code):
my $b = '1';
sub print_b
{
print $b;
}
$b = '2';
print_b();
You could use a reference to the original variable, and dereference it as needed:
my $b = '1';
my $a = \$b;
$b = '2';
print $$a;
What you want is not lazy evaluation, but late binding. To get it in Perl, you need to use eval.
my $number = 3;
my $val = "";
my $x = '$val="${number}"';
$number = 42;
eval $x;
print "val is now $val\n";
Be advised that eval is usually inefficient as well as methodically atrocious. You are almost certainly better off using a solution from one of the other answers.
Perl will interpolate a string when the code runs, and i don't know of a way to make it not do so, short of formats (which are ugly IMO). What you could do, though, is change "when the code runs" to something more convenient, by wrapping the string in a sub and calling it when you need the string interpolated...
$b = "1";
my $a = sub { "\$b is $b" };
$b = "2";
print &$a;
Or, you could do some eval magic, but it's a bit more intrusive (you'd need to do some manipulation of the string in order to achieve it).
As others have mentioned, Perl will only evaluate strings as you have written them using eval to invoke the compiler at runtime. You could use references as pointed out in some other answers, but that changes the way the code looks ($$a vs $a). However, this being Perl, there is a way to hide advanced functionality behind a simple variable, by using tie.
{package Lazy;
sub TIESCALAR {bless \$_[1]} # store a reference to $b
sub FETCH {${$_[0]}} # dereference $b
sub STORE {${$_[0]} = $_[1]} # dereference $b and assign to it
sub new {tie $_[1] => $_[0], $_[2]} # syntactic sugar
}
my $b = 1;
Lazy->new( my $a => $b ); # '=>' or ',' but not '='
print "$a\n"; # prints 1
$b = 2;
print "$a\n"; # prints 2
You can lookup the documentation for tie, but in a nutshell, it allows you to define your own implementation of a variable (for scalars, arrays, hashes, or file handles). So this code creates the new variable $a with an implementation that gets or sets the current value of $b (by storing a reference to $b internally). The new method is not strictly needed (the constructor is actually TIESCALAR) but is provided as syntactic sugar to avoid having to use tie directly in the calling code.
(which would be tie my $a, 'Lazy', $b;)
You wish to pretend that $a refers to something that is evaluated when $a is used... You can only do that if $a is not truly a scalar, it could be a function (as cHao's answer) or, in this simple case, a reference to the other variable
my $b="1";
my $a= \$b;
$b="2";
print $$a;
I would like the ${b} to remain "unreplaced" until $a is needed.
Then I'd recommend eschewing string interpolation, instead using sprintf, so that you "interpolate" when needed.
Of course, on this basis you could tie together something quick(ish) and dirty:
use strict;
use warnings;
package LazySprintf;
# oh, yuck
sub TIESCALAR { my $class = shift; bless \#_, $class; }
sub FETCH { my $self = shift; sprintf $self->[0], #$self[1..$#$self]; }
package main;
my $var = "foo";
tie my $lazy, 'LazySprintf', '%s', $var;
print "$lazy\n"; # prints "foo\n"
$var = "bar";
print "$lazy\n"; # prints "bar\n";
Works with more exotic format specifiers, too. Yuck.
With warnings enabled, perl usually prints Use of uninitialized value $foo if $foo is used in an expression and hasn't been assigned a value, but in some cases it's OK, and the variable is treated as false, 0, or '' without a warning.
What are the cases where an uninitialized/undefined variable can be used without a warning?
Summary
Boolean tests
Incrementing or decrementing an undefined value
Appending to an undefined value
Autovivification
Other mutators
Boolean tests
According to the perlsyn documentation,
The number 0, the strings '0' and '', the empty list (), and undef are all false in a boolean context. All other values are true.
Because the undefined value is false, the following program
#! /usr/bin/perl
use warnings;
my $var;
print "A\n" if $var;
$var && print "B\n";
$var and print "C\n";
print "D\n" if !$var;
print "E\n" if not $var;
$var or print "F\n";
$var || print "G\n";
outputs D through G with no warnings.
Incrementing or decrementing an undefined value
There's no need to explicitly initialize a scalar to zero if your code will increment or decrement it at least once:
#! /usr/bin/perl
use warnings;
my $i;
++$i while "aaba" =~ /a/g;
print $i, "\n";
The code above outputs 3 with no warnings.
Appending to an undefined value
Similar to the implicit zero, there's no need to explicitly initialize scalars to the empty string if you'll append to it at least once:
#! /usr/bin/perl
use warnings;
use strict;
my $str;
for (<*>) {
$str .= substr $_, 0, 1;
}
print $str, "\n";
Autovivification
One example is "autovivification." From the Wikipedia article:
Autovivification is a distinguishing feature of the Perl programming language involving the dynamic creation of data structures. Autovivification is the automatic creation of a variable reference when an undefined value is dereferenced. In other words, Perl autovivification allows a programmer to refer to a structured variable, and arbitrary sub-elements of that structured variable, without expressly declaring the existence of the variable and its complete structure beforehand.
For example:
#! /usr/bin/perl
use warnings;
my %foo;
++$foo{bar}{baz}{quux};
use Data::Dumper;
$Data::Dumper::Indent = 1;
print Dumper \%foo;
Even though we don't explicitly initialize the intermediate keys, Perl takes care of the scaffolding:
$VAR1 = {
'bar' => {
'baz' => {
'quux' => '1'
}
}
};
Without autovivification, the code would require more boilerplate:
my %foo;
$foo{bar} = {};
$foo{bar}{baz} = {};
++$foo{bar}{baz}{quux}; # finally!
Don't confuse autovivification with the undefined values it can produce. For example with
#! /usr/bin/perl
use warnings;
my %foo;
print $foo{bar}{baz}{quux}, "\n";
use Data::Dumper;
$Data::Dumper::Indent = 1;
print Dumper \%foo;
we get
Use of uninitialized value in print at ./prog.pl line 6.
$VAR1 = {
'bar' => {
'baz' => {}
}
};
Notice that the intermediate keys autovivified.
Other examples of autovivification:
reference to array
my $a;
push #$a => "foo";
reference to scalar
my $s;
++$$s;
reference to hash
my $h;
$h->{foo} = "bar";
Sadly, Perl does not (yet!) autovivify the following:
my $code;
$code->("Do what I need please!");
Other mutators
In an answer to a similar question, ysth reports
Certain operators deliberately omit the "uninitialized" warning for your convenience because they are commonly used in situations where a 0 or "" default value for the left or only operand makes sense.
These are: ++ and -- (either pre- or post-), +=, -=, .=, |=, ^=, &&=, ||=.
Being "defined-or," //= happily mutates an undefined value without warning.
So far the cases I've found are:
autovivification (gbacon's answer)
boolean context, like if $foo or $foo || $bar
with ++ or --
left side of +=, -=, or .=
Are there others?
Always fix warnings even the pesky annoying ones.
Undefined warnings can to be turned off. You can do that by creating a new scope for the operation. See perldoc perllexwarn for more info. This method works across all versions of perl.
{
no warnings 'uninitialized';
my $foo = "foo" + undef = "bar";
}
For a lot of the binary operators, you can use the new Perl 5.10 stuff, ~~ and //; See perldoc perlop for more info.
use warnings;
my $foo = undef;
my $bar = $foo // ''; ## same as $bar = defined $foo ? $foo : ''
also is the //= variant which sets the variable if it is undefined:
$foo //= '';
The Smart Matching (~~) operator is kind of cool, and permits smart comparisons, this is kind of nifty check it out in perldoc perlsyn:
use warnings;
my $foo = "string";
say $foo eq undef; # triggers warnings
say $foo ~~ undef; # no undef warnings
The real answer should be: why would you want to turn on that warning? undef is a perfectly good value for a variable (as anyone who's ever worked with a database can tell you), and it often makes sense to differentiate between true (something happened), false (nothing happened) and undef (an error occurred).
Rather than saying
use strict;
use warnings;
say
use common::sense;
and you'll get all the benefits of warnings, but with the annoying ones like undefined variables turned off.
common::sense is available from the CPAN.