For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > October 2006 > Scope









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Scope
John Ackley

2006-10-01, 9:58 pm

simple scope question
when is a global not a global?
or how to get a value from inside a while() to the outside?

two tests-extracted from much large program to show my problem
-------------------- test 1 --------------------------------
my $count;
my $service;

while( ($service) = $SERVICE->fetchrow_array ) {
$count++;
print "count $count service.number <$service>\n";
}
print "service.number <$service>\n";

produces output:
$ ./test.pl
count 1 service.number <229>
Use of uninitialized value at ./test.pl line 26.
service.number <>
note:same results with/without () around $service
----------------- test 2 ---------------------------------
my $count;
my $servicenumber;

while( my ($service) = $SERVICE->fetchrow_array ) {
$count++;
print "count $count service.number <$service>\n";
$servicenumber = $service;
}
print "service.number <$servicenumber>\n";
(note: the "my" on $service was required by strict)

produces desired result:
$ ./test.pl
count 1 service.number <229>
service.number <229>

----------------------------------------------

header of test.pl is
#! /usr/bin/perl -w

use strict;
use DBI;

my $driver = DBI->install_driver('mysql') or die;
my $max = DBI-> connect('DBI:mysql:database=max','max','
pass') or die;

my $SERVICE = $max->prepare("\
SELECT number
FROM service
WHERE state = 0

----------------------------------------------------
$ perl -v
This is perl, version 5.005_03 built for i386-freebsd

AND d03 = ?") or die;
$SERVICE->execute('0020a6-5a83b4') or die;




Paul Lalli

2006-10-01, 9:58 pm

John Ackley wrote:
> simple scope question
> when is a global not a global?
> or how to get a value from inside a while() to the outside?
>
> two tests-extracted from much large program to show my problem
> -------------------- test 1 --------------------------------
> my $count;
> my $service;
>
> while( ($service) = $SERVICE->fetchrow_array ) {
> $count++;
> print "count $count service.number <$service>\n";
> }
> print "service.number <$service>\n";
>
> produces output:
> $ ./test.pl
> count 1 service.number <229>
> Use of uninitialized value at ./test.pl line 26.
> service.number <>
> note:same results with/without () around $service


This is all exactly as expected. The first time your while()
conditional is evaluated, $service gets the value 229. 229 is true, so
the while() loop executes. The second time the while() conditional is
evaluated, fetchrow_array returns undefined, so $service gets the
undefined value. Undefined is false, so the loop is not executed, and
terminates. That's why $service has undef after the end of the loop.

> ----------------- test 2 ---------------------------------
> my $count;
> my $servicenumber;
>
> while( my ($service) = $SERVICE->fetchrow_array ) {
> $count++;
> print "count $count service.number <$service>\n";
> $servicenumber = $service;
> }
> print "service.number <$servicenumber>\n";
> (note: the "my" on $service was required by strict)
>
> produces desired result:
> $ ./test.pl
> count 1 service.number <229>
> service.number <229>


Right. Because you set $servicenumber to $service only during the
execution of the while loop - when, by definition, $service must have a
true value. The second time the conditional is executed, $service gets
undef, which causes the loop to terminate immediately - $servicenumber
is not set, and so remains whatever it was.

I'm not sure what your actual question is. If you're asking for an
explanation of the actual results, I hope I've provided it. If you're
asking for a better way.... I really don't think there is.

Paul Lalli

Charles K. Clarkson

2006-10-02, 3:58 am

John Ackley wrote:


: while( ($service) = $SERVICE->fetchrow_array ) {

According to the DBI docs:

"If there are no more rows or if an error occurs,
then fetchrow_array returns an empty list."

When a value is returned, $service is set to that value.
When we get to the end of the list, () is returned and
$service is set to the undefined value. Since it tests
false, the while loop stops with $service set to an undefined
value.

You can see this in the following script.

use strict;
use warnings;
use Data::Dumper 'Dumper';

my $service;

($service) = ();

print Dumper $service;

__END__


HTH,

Charles K. Clarkson
--
Mobile Homes Specialist
Free Market Advocate
Web Programmer

254 968-8328

Don't tread on my bandwidth. Trim your posts.

nobull67@gmail.com

2006-10-02, 7:58 am

Paul Lalli wrote:
> John Ackley wrote:


[color=darkred]
> The second time the while() conditional is
> evaluated, fetchrow_array returns undefined, so $service gets the
> undefined value. Undefined is false, so the loop is not executed, and
> terminates.


Actually that's not true.

The second time the while() conditional is evaluated, fetchrow_array
returns an empty list.

Because there are now more variables on the LHS of the assignment than
in the list $service gets the undefined value.

The scalar context return value of a list assignment is the number of
elements in the RHS list. This is zero. Zero is false so the loop is
not executed, and terminates.

If fetchrow_array had returned undef (i.e. a list containing one
element that was the undef value) then $service would still have been
undef but the loop would not have terminated.

> That's why $service has undef after the end of the loop.


That bit is right!

Paul Lalli

2006-10-02, 7:58 am

nobull67@gmail.com wrote:
> Paul Lalli wrote:
>
>
>
> Actually that's not true.
>
> The second time the while() conditional is evaluated, fetchrow_array
> returns an empty list.
>
> Because there are now more variables on the LHS of the assignment than
> in the list $service gets the undefined value.
>
> The scalar context return value of a list assignment is the number of
> elements in the RHS list. This is zero. Zero is false so the loop is
> not executed, and terminates.
>
> If fetchrow_array had returned undef (i.e. a list containing one
> element that was the undef value) then $service would still have been
> undef but the loop would not have terminated.


Huh. Well I'll be darned. You are absolutely correct. And in case
anyone else is/was , here's a script to illustrate:

#!/usr/bin/perl
use strict;
use warnings;

my $i = 0;
while (my ($foo) = func($i)) {
print "Foo: '$foo'\n";
$i++;
}

sub func {
my $val = shift;
return ('first', undef, 2)[$val];
}
__END__

The first time through, func will return 'first', then the undefined
value, then the integer 2, and finally the empty list. Output of this
script:

Foo: 'first'
Use of uninitialized value in concatenation (.) or string at ./clpm.pl
line 8.
Foo: ''
Foo: '2'

Thanks for the corrections and information!

Paul Lalli

Derek B. Smith

2006-10-02, 6:59 pm

-- "Charles K. Clarkson" <cclarkson@htcomp.net> wrote:

> John Ackley wrote:
>
>
> : while( ($service) = $SERVICE->fetchrow_array ) {
>
> According to the DBI docs:
>
> "If there are no more rows or if an error occurs,
> then fetchrow_array returns an empty list."
>
> When a value is returned, $service is set to
> that value.
> When we get to the end of the list, () is returned
> and
> $service is set to the undefined value. Since it
> tests
> false, the while loop stops with $service set to an
> undefined
> value.
>
> You can see this in the following script.
>
> use strict;
> use warnings;
> use Data::Dumper 'Dumper';
>
> my $service;
>
> ($service) = ();
>
> print Dumper $service;
>


John,

For a complete understanding of scope (not listerine)
: )
please read the following:
http://perl.plover.com/local.html#2...zed_Filehandles

and
http://www.perlmonks.org/?node_id=564448

Wow...opened my eyes and I now fully understand global
and non global variables.

________________________________________
__________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
Chad Perrin

2006-10-02, 6:59 pm

On Mon, Oct 02, 2006 at 07:15:38AM -0700, Derek B. Smith wrote:
>
> For a complete understanding of scope (not listerine)
> : )
> please read the following:
> http://perl.plover.com/local.html#2...zed_Filehandles
>
> and
> http://www.perlmonks.org/?node_id=564448
>
> Wow...opened my eyes and I now fully understand global
> and non global variables.


Hah. That's the PerlMonks thread I tried to send to the list
previously, and accidentally replied directly to the OP rather than
sending to the list. Being the lazy soul I am, I didn't bother to
resend.

I'm glad *someone* sent it to the list at large, in case it's useful to
more than just the OP.

--
CCD CopyWrite Chad Perrin [ http://ccd.apotheon.org ]
unix virus: If you're using a unixlike OS, please forward
this to 20 others and erase your system partition.
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2009 codecomments.com