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

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

Thread Previous | Thread Next
Linda Walsh via RT
September 29, 2013 20:25
[perl #120047] perl should enable "$_" for use before calling subs
Message ID:
On Sun Sep 29 05:57:53 2013, aristotle wrote:
> * Linda Walsh <> [2013-09-29 11:30]:
> > 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.
> I will assume you are referring to map, grep and foreach here, because
> I do not know what you could be talking about otherwise. It would help
> if you were explicit and specific, however.
Those were ones I could think of off hand, but I didn't want to give a
closed list as I wasn't sure if that was an exhaustive list.  But to the
point, there are many places where, if you are following the advice to
use the strengths of perl and use its idioms, '$_' is assumed as an
operand -- then the user needs to save it for use in the local sub, 
***without propagating their changed value*** to called subs.  Using
local in such a case wouldn't have that effect.   

There may also be cases where passing the changed value is desired, but
that's why lexical "$_" was created -- to allow $_ to use it locally,
but not propagate it's value to called routines.  Except that feature
was removed without deprecation in 5.18 and replaced with an
experimental one (but that's a different bug/discussion).

> > 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.
> Au contraire, one can find such cases very easily when one understands
> why some do and others don’t.
     So you can think of cases where builtin's should be able to modify
and do subcalls with modified versions of "$_", where user-level code, 
saving "$_", and using it should fail?   I don't think your statement
answered the scenario.
> The reason is that map, grep, foreach do this because they alias $_ to
> another scalar, rather than changing the contents of the scalar $_ was
> previously pointing to. There are plenty of other builtins, namely any
> that do *not* alias $_ but instead modify its contents, which *will*
> trigger a read-only value modification exception if you invoke them
> while $_ refers to a read-only scalar.
    Leon's advice was use local (which has side effects in changing
the value of $_ in called subs), "Or better yet, just use a lexical
variable."  To make use of the idiom of search strings search $_ by
default, I would agree that one should save $_ in a lexical variable (as
I do in my in the original code), and then be able to use it.

    Unfortunately, saving "$_", doesn't allow it's use when it has been
aliased to a constant.

> The difference between these is that localising means you’ll be changing
> a copy of $some_modifiable_value, so any modifications to $_ will not be
> reflected in that variable. Aliasing means you are literally making $_
> refer to the same scalar as $some_modifiable_value, and therefore any
> changes to either one will be reflected in the other – just like map,
> grep and foreach do. (Well, you are literally using foreach to get the
> aliasing, of course.)
I'm aware of the difference.

> > 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.
> The design reason is that a user subroutine may well be interested in
> the value that was previously in $_, even if that was a read-only value.
> The language has no way to know what the user intended so it doesn’t try
> to, as well it oughtn’t.
    Au contraire!  This isn't the case.
    1) both of us know that if I use a for loop in my code and then
call subs below that it ***WON'T*** use the value aliased to a user
    2) If someone was to use "local" it would not only allow writing to
$_, but also propagate it to called subs similarly to 1.  So both of
those cases clearly allow $_ to be trampled -- and using either causes
the previous value of "$_" to be lost while you are in the modified context.

    3) if you *wanted* to use the value of $_, but only in your local
sub, being able to *save* it's value as I do above (above meaning as
located on bug-report webpage): "my $__=$_".   Now the value is saved
and the user's value of $_ is used to calculate the answer.  What
doesn't work is the READ-ONLY state of "$_".  I didn't say the original
"$_" should be overwritten and ignored as is done with the builtins
above, and "local".  I said the read-only state should be made local to
the loop where it resides.  Out of that loop, the value remains, but the
read-only state is removed.  Any changes to "$_" are lost upon 
exiting a called context that returns to the initial loop.

    Think of perl making "$_" "COW" in called subs.  If a user 
assigns or changes "$_" when it is readonly, a lexical copy is made just
as in a "for/map/grep".  That lexical copy goes out of effect,
lexically (not like 'local' which propagates changed values to called subs).

The purpose here was to all allow copy-on-write semantics of $_ in a
subroutine/function when "$_" was "read-only" -- AND only when you are
not in the lexical context that makes "$_" 'read-only' -- i.e. 
if you are in a subroutine that is outside the RO-making loop.

> > 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?
> Just because you cannot see a reason does not automatically mean that
> there cannot be any and that this must therefore be an oversight. 
> There *is* another option, that you may be overlooking or
> simply misunderstanding something.
Absolutely!   That's why I asked for an example where my solution
wouldn't work.

    Do you need it spelled out more formally?

> > 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
> > […]
> This is part of another ticket and off-topic in this one.
     Not exactly off topic, since people made up that I didn't
acknowledge that it was behaving according to documentation -- but that
I felt the design was problematic and asked for design reasons why my
specific solution would be untenable.

No one in their responses did  this -- so the fact that no one could
respond "in context" before closing out the bug, was exactly what
happened, again.   

If there wasn't a concern that some people might not be stuck in certain
behaviors or responses when dealing with issues I raise, I wouldn't have
made the comment.

So can this bug be reopened now that it is clear that it isn't resolved,
and that rejecting it on the grounds that the self-referential pointer
of current documentation or behavior, pointing to itself, will not
answer this question.

I proposed a specific solution to this flaw, no one has shown why it
wouldn't work or why it shouldn't be implemented.

via perlbug:  queue: perl5 status: rejected

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