Path: utzoo!attcan!uunet!snorkelwacker!usc!rutgers!mcnc!thorin!currituck.cs.unc.edu!tell From: tell@currituck.cs.unc.edu Newsgroups: comp.lang.perl Subject: call-by-reference, $#_, and local() Message-ID: <15096@thorin.cs.unc.edu> Date: 11 Jul 90 16:17:20 GMT Sender: news@thorin.cs.unc.edu Reply-To: tell@currituck.cs.unc.edu () Organization: University Of North Carolina, Chapel Hill Lines: 130 I think I may have found two (possibly related) bugs in Perl 3.0 pl 18, or at least some really subtle points. I've been able to reproduce them with the short programs below, extracted from a much larger program. I'm trying to pass several arrays to a subroutine by reference so the subroutine can fill them in. ----------------------------------------------------------------------------- Problem 1. Subroutine next_wire_al reads a record from a file and attempts to use $#_ (the number of arguments) to behave somewhat differently in the presence of various arguments. Argument 0 is a string that is set by the routine. Arguments 1, 2, and optionaly 3 are arrays passed by reference with with "*." Argument 3 can be omitted. When the test "if($#_ == 3)" is present, the third argument gets munged as the routine returns; the @attribs array prints out as empty in the calling routine. The value of $#_ printed is always correct, and the if() always does the right thing as evidenced by the print within it. Stepping through with the debugger suggests that the call-by-reference is not working with the "if($#_ == 3)" there (@wattribs is not identical to @attribs in this case). So, what's going on? I've read the manual several times and don't see anything special about $#_. #!/usr/local/contrib/bin/perl &read_wirelist; sub read_wirelist { local($wire, @ports, @power, @attribs); &next_wire_al($wire, *ports, *power, *attribs); # &next_wire_al($wire, *ports, *power); print "wire=$wire\n"; print "ports = @ports\n"; print "power = @power\n"; print "attribs = @attribs\n"; } sub next_wire_al { local(*mports) = $_[1]; local(*pnames) = $_[2]; local(@allattribs); local($do_wattribs); print "$#_ args\n"; ## Comment out the next line and the closing brace and the program works OK. if($#_ == 3) { local(*wattribs) = $_[3]; print "getting attributes\n"; $do_wattribs = 1; } # a dummy line - we really read a file $line = "D0 MP=D0 type=bidirectional PWR=VGG"; ($_[0], @allattribs) = split(' ', $line); @mports = grep(s/^MP=//, @allattribs); # module ports @pnames = grep(s/^PWR=//, @allattribs); # power names if($do_wattribs) { @wattribs = grep(/\w*=\w*/, @allattribs); if ($#wattribs>=0) { print "attribs = ",join(';', @wattribs), "\n"; } } 1; } ----------------------------------------------------------------------------- Problem 2: In this shorter bit of code, the local(@at) call in get_at appears to hide @at in routine one, even though we've passed a reference to it. If this behavior is correct, it seems really counterintuitive. I would think that taking *at in the call to routine get_at would put the "pointer" to the original array into $_[0], and that later calling local(@at) should only hide that original array @at when it is accessed by name (creating a new @at, but not changing where the "pointer" from the * operator points.) sub one { local(@attribs, @at); @attribs = ("foo"); &get_at(*at); print "attribs = @attribs\n"; print "at = @at\n"; } sub get_at { local(@at); # change @at to @foo and program works OK. local(*at2) = $_[0]; push(@at2, "got_at"); } &one; perl -v says: >$Header: perly.c,v 3.0.1.5 90/03/27 16:20:57 lwall Locked $ >Patch level: 18 > >Copyright (c) 1989, 1990, Larry Wall > >Perl may be copied only under the terms of the GNU General Public License, >a copy of which can be found with the Perl 3.0 distribution kit. While I've got everybody's attention (especially Larry's) is there any chance that perl -d will ever be usable on 'do' files (library routines, for example)? How about hooks so one can look at the arguments to a subroutine- glancing through perldb, I understand why with the current debugger implentation $_[0] gives me the line number and not what I expect at the point where the program is stopped, but it is really confusing at times. Thanks for any help & advice, Steve -------------------------------------------------------------------- Steve Tell tell@wsmail.cs.unc.edu CS Grad Student, UNC Chapel Hill. "If you insist on spending $10000 on 68030 technology, may we humbly suggest you buy three Amiga 3000's."