develooper Front page | perl.perl5.porters | Postings from September 2013

[perl #120047] perl should enable "$_" for use before calling subs

Thread Next
Leon Timmermans via RT
September 29, 2013 11:43
[perl #120047] perl should enable "$_" for use before calling subs
Message ID:
On Sun Sep 29 02:26:28 2013, LAWalsh wrote:
> This is a bug report for perl from,
> generated with the help of perlbug 1.39 running under perl 5.16.2.
> -----------------------------------------------------------------
> [Please describe your issue here]
> I wasn't sure if this should be filed as a bug but the more
> I think about it, perl without "$_" would be like making
> hardware registers read-only then calling subroutines and expecting
> them to work without their main registers.
> While it is usually possible to program without using "$_", it
> is considered efficient and a sign of language mastery to make full
> use of perl's idiom and not try to use it as a general purpose
> programming language.  using $_ in for loops/ grep, map, and
> an implied operand for many perl builtins is considered an effective
> use of the language.  It is counter productive to disable the usage
> of ideomatic perl by making $_ "read-only" in called-subs.
> Instead, when $_ is aliased to a constant, when code control exits the
> lexical scope of the for loop by calling funcs outside of the loop,
> the readonly status of $_ needs to be "noted" and saved as part of the
> current context.  In subroutines, though they need to be able to use
> $_ "normally", or it places an undo and unnecessary constraing on
> those developing libraries.  They don't know where they will be called
> from, thus, one could argue that any code that is "called" cannot use
> "$_".  This places a large handicap on all "called code".  Any
>    modifications
> done to "$_" in sub functions would be ignored upon return to the
>    lexical
> scope where $_ was read-only.
> It is the case that various "builtin"s already do this.  So one would
>    be
> hard pressed to find a case where builtin's can do it (can in turn
>    call
> other subs where now "$_" is no longer R/O), but not allow
> user-level code that that tries to use $_ ideomatically, but magically
> fails due to $_ being protected.
> Regardless of documenation that may justify this behavior, I would
>    like to
> see the design reasons for this behavior if such is to be found.
> I see no logic in disabling $_, **randomly*** (based on callstack) in
> a sub-function or library call but allowing it for built-ins.  There
> are things that can't be done without extraneous declarations without
> using the $_ register (like a postfix for-loop).
> Can this oversite be fixed?  Can people not make stuff up
> as to why it can't or shouldn't be done as was done when I suggested
> allowing  explicitly declared local vars to be retained over a goto
>    and
> not popped until the call-stack is popped, as in my mind, the
> target of the &goto was effectively becoming part of the initially
> called procedure, with the &goto allowing for a common back end for
> multiple front-end functions.  In that sense not popping local until
> the common back end is done makes sense.  But I was given a special
> case example that would have been better coded in a loop than trying
> to do tail recursion, which it turns out is not really that optimized
> at all.
> The way I see that one, BTW, is that the local decl remains in
> effect if the goto happens before exiting context that would
> pop-the local, but if the context where local was used is left
> before the goto, it would be popped as normal.  Anyway, I'm getting
> off topic.  This was about readonly $_ and how it shouldn't be
> imposed on out-of-scope subs as, truthfully, having routines that
> work for months to years fail because your code usually uses vars
> to iterate over in a for-loop, but having it fail in rare cases where
> a $_ pops up as read-only, is really an obscure design case that
> library writers shouldn't need to work about.
> It's just too quirky to have things like a "for" loop work but not
> similar while loop that may be better form to avoid list overhead.
> Short prog that determines iterations of rand picking a-c to match
> one of them -- iterated through for each a, b, c).
> Case 1 works fine,
> Case 2 fails
> perl -MP -we'use strict;
> #iterations of rand to match 1 of 3 items
> sub mysub { my $val=$_[0];
> 	my $cnt=0; my $__=$_;
> 	do {
> 		$_=(qw(x y z))[int(3*rand)];
> 		++$cnt;
> 	} while $_ ne $val;
> 	$_=$__;
> 	return $cnt
> }
> our ($x, $y, $z);
> P "case1";
> our @vars=qw(x y z);
> for (@vars) {
> 	no strict qw(refs);
> 	$$_=mysub($_);
> 	P "%s", [$x,$y,$z];
> }
> P "case2";
> for (qw(x y z)) {
> 	no strict qw(refs);
> 	$$_=mysub($_);
> 	P "%s", [$x,$y,$z];
> }
> '
> =====
> output:
>  /tmp/t1
> case1
> [1, ∄, ∄]
> [1, 3, ∄]
> [1, 3, 1]
> case2
> Modification of a read-only value attempted at -e line 7.
> ====
> It's not hard to see how this could increase unreliability
> of code and how fixing it would make code more reliable.

When using $_ in a subroutine and you do not want it to affect or or be
affected by the calling environment, you should use local on it. Or
better yet, just use a lexical variable. Not doing so is a bug, your
bug. Perl is behaving as intended and expected.

Closing this as not-a-bug

via perlbug:  queue: perl5 status: new

Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About