Lexical scoping question.

L

Louis.

Hi,

The below script will print "var is apple". I find this weird, because
in textbooks you are taught to pass variable to subroutines as
parameters. What is the point of doing this, if the variable is
visible anyway?

How can I make the variable exist in main and yet be invisible to the
subroutine? I know I can create another variable with "my" and with
the same name in the subroutine. This will block the subroutine from
seeing variable in main, but is this really the way to do it, it seems
very cumbersom.

TIA,
Louis.

my $var = "apple";
routine();

sub routine {
print "var is $var.\n";
}




Solution???

{
my $var = "apple";
routine($var);
}

sub routine {
my $var = $_[0];
print "var is $var.\n";
}
 
L

Larry

Louis. said:
Hi,

The below script will print "var is apple". I find this weird, because
in textbooks you are taught to pass variable to subroutines as
parameters. What is the point of doing this, if the variable is
visible anyway?

How can I make the variable exist in main and yet be invisible to the
subroutine? I know I can create another variable with "my" and with
the same name in the subroutine. This will block the subroutine from
seeing variable in main, but is this really the way to do it, it seems
very cumbersom.

TIA,
Louis.

my $var = "apple";
routine();

sub routine {
print "var is $var.\n";
}




Solution???

{
my $var = "apple";
routine($var);
}

sub routine {
my $var = $_[0];
print "var is $var.\n";
}

#include <stdio.h>

int print_a();
int a = 5;
int main()
{
print_a();
}
int print_a()
{
printf("%d\n",a);
}

looks like you can mess it up in C too.
 
A

Arndt Jonasson

The below script will print "var is apple". I find this weird, because
in textbooks you are taught to pass variable to subroutines as
parameters. What is the point of doing this, if the variable is
visible anyway?

How can I make the variable exist in main and yet be invisible to the
subroutine? I know I can create another variable with "my" and with
the same name in the subroutine. This will block the subroutine from
seeing variable in main, but is this really the way to do it, it seems
very cumbersom.

my $var = "apple";
routine();

sub routine {
print "var is $var.\n";
}

You can declare the function before the variable:

sub routine {
print "var is $var.\n";
}

my $var = "apple";
routine();
 
C

Chris Mattern

Louis. said:
Hi,

The below script will print "var is apple". I find this weird, because
in textbooks you are taught to pass variable to subroutines as
parameters. What is the point of doing this, if the variable is
visible anyway?

You avoid using global effects because it's good programming practice
and significantly improves the maintainability of your scripts, not
because the language makes you do it.
How can I make the variable exist in main and yet be invisible to the
subroutine?

Lexical variables don't exist in main; they don't exist in *any*
package. That's why they're lexical. Lexical variables are
statically scoped to the block that contains them. If they're
not contained in a block, they're scoped to the file they're in.
I know I can create another variable with "my" and with
the same name in the subroutine. This will block the subroutine from
seeing variable in main, but is this really the way to do it, it seems
very cumbersom.

Really? Doesn't seem that way to me. YMMV, I guess.
TIA,
Louis.

my $var = "apple";
routine();

sub routine {
print "var is $var.\n";
}




Solution???

{
my $var = "apple";
routine($var);
}

sub routine {
my $var = $_[0];
print "var is $var.\n";
}

Yes, that's how you do it. You should *always* define lexicals in the
smallest possible block. A good way to help you do this is to get in
the habit of not declaring variables until you need them.
--
Christopher Mattern

"Which one you figure tracked us?"
"The ugly one, sir."
"...Could you be more specific?"
 
D

David K. Wall

Louis. said:
The below script will print "var is apple". I find this weird,
because in textbooks you are taught to pass variable to
subroutines as parameters. What is the point of doing this, if the
variable is visible anyway?

I think the point is that you have a choice. If you want to use a
variable from a larger scope inside a subroutine you're free to do so.
Perl itself doesn't pass judgement on it; Perl *programmers*, on the
other hand....
 
G

Gunnar Hjalmarsson

David said:
I think the point is that you have a choice. If you want to use a
variable from a larger scope inside a subroutine you're free to do so.
Perl itself doesn't pass judgement on it;

That's not always true.

sub outer {
my $var = 'apple';
sub inner {
".. but \$var is still '$var' acc. to inner().\n"
}
if (shift) {
$var =~ s/apple/banana/;
print "\$var is now '$var' ..\n";
print inner();
return;
}
print "\$var is '$var'.\n";
}

outer();
outer(1);

Outputs:
$var is 'apple'.
$var is now 'banana' ..
... but $var is still 'apple' acc. to inner().

(plus the warning: Variable "$var" will not stay shared)

When running a program under mod_perl, this phenomenon may occur also
when non-nested subroutines use file scoped variables.
Perl *programmers*, on the other hand....

Making passing of variables a habit is not only a matter of style.
 
D

David K. Wall

Gunnar Hjalmarsson said:
That's not always true.

sub outer {
my $var = 'apple';
sub inner {
".. but \$var is still '$var' acc. to inner().\n"
}
if (shift) {
$var =~ s/apple/banana/;
print "\$var is now '$var' ..\n";
print inner();
return;
}
print "\$var is '$var'.\n";
}

outer();
outer(1);

Outputs:
$var is 'apple'.
$var is now 'banana' ..
.. but $var is still 'apple' acc. to inner().

(plus the warning: Variable "$var" will not stay shared)

When running a program under mod_perl, this phenomenon may occur
also when non-nested subroutines use file scoped variables.

I don't see a problem there. The results might not be what you
expect, but perl will still let you use a variable from a larger
scope inside a subroutine, and even warn you when it sees what it
"thinks" are possibly unintended consequences. Doesn't seem very
judgemental to me.

Making passing of variables a habit is not only a matter of style.

I certainly never intended to say that, but since you're on about it,
how about expanding on that comment? Offhand I can think of two
situations where you HAVE to pass parameters to a sub: recursive
functions and OOP.

(For some truly tangled code that uses global variables for
everything, take a look at the Greymatter blogging code. Urgh...)
 
G

Gunnar Hjalmarsson

I don't see a problem there. The results might not be what you
expect, but perl will still let you use a variable from a larger
scope inside a subroutine, and even warn you when it sees what it
"thinks" are possibly unintended consequences. Doesn't seem very
judgemental to me.

Potentially unintended consequences is a strong reason to not do it,
whether "judgemental" is the accurate term or not. ;-)
I certainly never intended to say that, but since you're on about it,
how about expanding on that comment?

I was simply referring to my example. The principal reason for passing
variables to subs, AFAIU, is that it makes the code easier to maintain.
The point I was trying to make was that, besides its making the code
less maintainable, there are situations where using lexical variables in
a sub, when they are scoped outside, may directly affect the expected
result.
 
M

Michael Powe

Louis> Hi, The below script will print "var is apple". I find this
Louis> weird, because in textbooks you are taught to pass variable
Louis> to subroutines as parameters. What is the point of doing
Louis> this, if the variable is visible anyway?

Louis> How can I make the variable exist in main and yet be
Louis> invisible to the subroutine? I know I can create another

Use 'anonymous' blocks. Any variable declared with 'my' outside a
block has file scope. To permit the variable only a local scope, put
it in a block like this:

c:\src>type test.pl
type test.pl
#!perl

use strict;

{
my $var = "string";

}

print $var;

c:\src>test.pl
test.pl
Global symbol "$var" requires explicit package name at C:\src\test.pl line 10.
Execution of C:\src\test.pl aborted due to compilation errors.

I use these blocks for encapsulating variables all the time. Helps
protect me from myself. ;-)

In python, btw, it is a common idiom to define a main() function in
your script, which serves the same purpose of maintenance of scope.

mp
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top