insaniac has asked for the wisdom of the Perl Monks concerning the following question:
sisters, bwothers,
Like the title says, undef is giving me horrible nightmares all of a sudden.
I have two variables which I use in a for loop. At the end of that loop, I undef two variables, which are created at the beginning of the loop. Now, in one cycle, the two variables were not empty et al, and contained data from a previous loop... which of course caused lots of evil ;-)
my code looks something like this:
for my $mode (@probe_modes) {
my (@source,@destination);
create_map_file $mode;
get_elements; # @source and @destination are filled here
scan_matrix $mode;
undef(@source);
undef(@destination);
}
I'm sure it's the undef that's causing the problem, because the first two subroutines should first check if the arrays need to be filled, and one will actually fill. The one that's checking reports that it's not going to fill (and it doesn't, i checked) and the second one says it's not filling, but there's data in the array of the previous loop.
I'm using:
This is perl, v5.6.1 built for sun4-solaris-64int
(with 48 registered patches, see perl -V for more detail)
Summary of my perl5 (revision 5.0 version 6 subversion 1) configuratio
+n:
Platform:
osname=solaris, osvers=2.9, archname=sun4-solaris-64int
uname='sunos localhost 5.9 sun4u sparc sunw,ultra-1'
config_args=''
hint=recommended, useposix=true, d_sigaction=define
usethreads=undef use5005threads=undef useithreads=undef usemultipl
+icity=undef
useperlio=undef d_sfio=undef uselargefiles=define usesocks=undef
use64bitint=define use64bitall=undef uselongdouble=undef
Compiler:
cc='cc', ccflags ='-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
optimize='-xO3 -xdepend',
cppflags=''
ccversion='Sun WorkShop', gccversion='', gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=87654321
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=1
+6
ivtype='long long', ivsize=8, nvtype='double', nvsize=8, Off_t='of
+f_t', lseeksize=8
alignbytes=8, usemymalloc=n, prototype=define
Linker and Libraries:
ld='cc', ldflags =''
libpth=/lib /usr/lib /usr/ccs/lib
libs=-lsocket -lnsl -ldl -lm -lc
perllibs=-lsocket -lnsl -ldl -lm -lc
libc=/lib/libc.so, so=so, useshrplib=true, libperl=libperl.so
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-R /usr/
+perl5/5.6.1/lib/sun4-solaris-64int/CORE'
cccdlflags='-KPIC', lddlflags='-G'
Thanks !
--
to ask a question is a moment of shame
to remain ignorant is a lifelong shame
Re: The weirdest problem with undef
by davorg (Chancellor) on Dec 22, 2004 at 10:09 UTC
|
As others have said, it looks like you're probably accessing two different sets of variables called @source and @destination. One is the lexical set that you are creating with the "my" call at the start of the loop and the other is the package variable set that you are setting in the "get_elements" call.
The two best pieces of advice that I can give you are:
- Stop relying on side-effects to populate global variables
- Turn on "use strict" and "use warnings" so you can see where you are unwittingly using package variables
--
< http://www.dave.org.uk>
"The first rule of Perl club is you do not talk about
Perl club." -- Chip Salzenberg
| [reply] [Watch: Dir/Any] |
Re: The weirdest problem with undef
by dave_the_m (Monsignor) on Dec 22, 2004 at 10:01 UTC
|
Your code can't possibly be doing what you think it's doing.
my variables are lexically scoped, which means
they can't be seen outside the block of code they are delcared
in. Thus, get_elements can't possibly be filling
the arrays
Dave. | [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] |
|
| [reply] [Watch: Dir/Any] |
|
|
|
Re: The weirdest problem with undef
by sasikumar (Monk) on Dec 22, 2004 at 11:05 UTC
|
Hi
Its always better to use strict before u start a perl program. Most of the times the problem comes because we are not clear of the scoping of the perl variables. Better to use strict.
In your case using strict will solve all the problems that you have.
Thanks
Sasi kumar
| [reply] [Watch: Dir/Any] |
|
yeah, but like i said in a previous reply: i didnt and i explained why... bear with me these beginner mistakes, ok?
btw: strict will _show_ the problems i have, not solve :-p i will have to do the solving part, if i'm smart enough..
--
to ask a question is a moment of shame
to remain ignorant is a lifelong shame
| [reply] [Watch: Dir/Any] |
Re: The weirdest problem with undef
by steves (Curate) on Dec 22, 2004 at 10:03 UTC
|
How is get_elements filling @source and
@destination if they're not being passed to it
and they're lexical variables with visibility only in
your loop?
It might help to see more of the code.
| [reply] [Watch: Dir/Any] |
Re: The weirdest problem with undef
by dirac (Beadle) on Dec 22, 2004 at 15:19 UTC
|
for my $mode (@probe_modes) {
local (@source,@destination);
create_map_file $mode;
get_elements; # @source and @destination are filled here
scan_matrix $mode;
@source =();
@destination =();
}
| [reply] [Watch: Dir/Any] |
|
| [reply] [Watch: Dir/Any] |
|
Which is a quick hack the OP indeed had already found himself. Still it is nothing but byzantine logic to avoid what parameter passing is exactly for.
Ciao ciao!
| [reply] [Watch: Dir/Any] |
Re: The weirdest problem with undef
by saberworks (Curate) on Dec 22, 2004 at 18:20 UTC
|
In this case your best bet would be to declare my (@array1, @array2) before the for loop if you want them to be available to your subroutines.
You are not having a problem with undef, you are having a problem variable scoping.
As others have mentioned, you should be using strict - you said it won't help you solve the problem, but how can you solve the problem when you clearly don't understand what the problem is? Using strict will help you figure out what the problem is so you can at least look in the right direction.
Here's what I used to test your code:
#!/usr/bin/perl
use strict;
foreach my $item ('top', 'heavy', 'fool') {
my (@array1, @array2);
a_function($item);
print "@array1\n";
print "@array2\n";
}
sub a_function {
my $item = shift;
push @array1, 'crap';
push @array2, 'dumb';
}
This gave me errors like this:
Global symbol "@array1" requires explicit package name at ./test_loop.
+pl line 18.
Global symbol "@array2" requires explicit package name at ./test_loop.
+pl line 19.
Execution of ./test_loop.pl aborted due to compilation errors.
This clearly tells me that the subroutine is looking for global variables. Declaring them as my inside a loop doesn't create global variables. So moving them to the top, like this, works fine:
...
my (@array1, @array2);
foreach my $item ('top', 'heavy', 'fool') {
...
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
What if the subroutines had been exported from another package?
| [reply] [Watch: Dir/Any] |
|
{
my $var;
sub bus {
$var++;
}
}
myself, occasionally. But not as an alternative to parameter passing... | [reply] [Watch: Dir/Any] [d/l] |
|
|