Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lexical scope of my

Tags:

perl

Pretty much every perl program written uses this idiom:

{
open(my $fh, '>>', $filename) || die "you lose";
print $fh $blah;
}

However, I don't want to die, I want to just skip the print. So I write:

{
print "you lose\n" unless (open(my $fh, '>>', $filename) and print $fh $blah);
}

and get "Can't use an undefined value as a symbol reference at ./o.pl line 5" for my trouble.

Removing the my (bad form) eliminates this error, as does:

{
my $fh;
print "you lose\n" unless (open($fh, '>>', $filename) and print $fh $blah);
}

but why?

Why, in the broken code, doesn't $fh exist from open(my $fh... to the close of the block (the })?

like image 288
John Hascall Avatar asked Dec 19 '13 14:12

John Hascall


People also ask

What is lexical scope example?

Here's an example of how lexical scoping works in JavaScript. var a = 10 var func = function (){ var b = 20; console. log("a and b is accessible (outer):", a, b); var innerFunc= function (){ var c = 30; console. log("a and b and c is accessible (inner):", a, b, c); } innerFunc(); return; } func(); console.

What is a lexical scope?

Lexical scope means that in a nested group of functions, the inner functions have access to the variables and other resources of their parent scope. This means that the child's functions are lexically bound to the execution context of their parents. Lexical scope is sometimes also referred to as static scope.

What is lexical scope in Python )?

Lexical scope means that an object's (memory) scope will that where it (i.e., the object) was defined. Let's take a function "f()", for instance. A function has an inner scope and an outer scope. In a lexically scoped language (eg, Python), the outer scope of " f() " will be the scope where the function was defined.

What is scope lexical scope in JavaScript?

What is Lexical Scope in JavaScript? Lexical scope is the definition area of an expression. In other words, an item's lexical scope is the place in which the item got created.


3 Answers

The my doesn't take effect until the end of the statement.

For that same reason, my $x = $x won't see the new $x on the right hand side of the statement. It'll see the old $x.

For example

use strict;
use warnings;

my $x = 42;

{
    my $x = $x + 1;
    print "inside, x = $x\n";
}

print "outside, x = $x\n";

This prints:

inside, x = 43
outside, x = 42

Your open statement is roughly equivalent to the inner my statement above. If you had $fh declared in the outer scope, surprising fun would happen: You'd probably end up printing to the wrong file.

like image 147
Joe Z Avatar answered Oct 03 '22 19:10

Joe Z


You may prefer

{
  open(my $fh, '>>', $filename) || warn "you lose";
  print $fh $blah if $fh->opened;
}

Of course you can also remove the warn if you wish.

If your Perl 5 is older than version 14 then you will need to add

use IO::File

to the header of your code.

like image 25
Borodin Avatar answered Oct 03 '22 17:10

Borodin


If you add strict and warnings to your program, you would get much more useful error messages:

use strict;
use warnings;

{
   my $filename = "test.txt";
   print "you lose\n" unless (open(my $fh, '>>', $filename) 
         and print {$fh} $blah);
}

__END__
Global symbol "$fh" requires explicit package name at test.pl line 6.
Global symbol "$blah" requires explicit package name at test.pl line 6.
Execution of test.pl aborted due to compilation errors.

The problem being that you can't declare and use a lexical variable in the same statement. $fh will only be available after the line with the open on it.

like image 34
Hunter McMillen Avatar answered Oct 03 '22 19:10

Hunter McMillen