Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EXPERIMENT] the lexical topic, my $_ #13172

Closed
p5pRT opened this issue Aug 16, 2013 · 8 comments
Closed

[EXPERIMENT] the lexical topic, my $_ #13172

p5pRT opened this issue Aug 16, 2013 · 8 comments

Comments

@p5pRT
Copy link

p5pRT commented Aug 16, 2013

Migrated from rt.perl.org#119315 (status was 'rejected')

Searchable as RT119315$

@p5pRT
Copy link
Author

p5pRT commented Aug 16, 2013

From @rjbs

Lexical topic was introduced in perl 5.10.0. Since then, it has come up mostly
on perl5 porters when it has caused confusion like this​:

  my $_; # or the now-gone implicit lexicalization by given

  # ... many lines ...

  someroutine(sub { ... $_ ... });

After a number of suggestions to deprecate the feature, it was deprecated
during the perl 5.17 series. Rafaël Garcia-Suarez objected in
http​://www.nntp.perl.org/group/perl.perl5.porters/2013/02/msg198987.html and
the feature was instead retroactively branded "experimental." The gambit (from
that thread) was to "buy time" to fix it.

That time has been bought, but what will the fix be?

We need to understand what would make this feature "salvaged," and then whether
it can be accomplished. If we can't figure out *any* acceptance criteria, then
the experiment seems doomed.

--
rjbs

@p5pRT
Copy link
Author

p5pRT commented Aug 16, 2013

From zefram@fysh.org

Ricardo SIGNES wrote​:

That time has been bought, but what will the fix be?

A conceivable class of fix would be implicit "our $_" on certain
lexical-scoping constructs, perhaps just on sub{}. However, this makes
things more complicated, so isn't a really appealing route.

I think the situations for which we wanted lexical $_ would be better
served by using a distinct name for the lexical topicaliser. It should
always be possible to explicitly specify the lexical variable name,
so that multiple such variables introduced by nested topicalisation
constructs don't interfere with each other. Where we want a topicaliser
name to be implicit, for conciseness, the implicit name should be
something other than $_. $# and $* are available.

Relatedly, triggering use of a lexical topicaliser by having "my $_"
in scope was a bad idea. The topicalising operator should provide
the lexical scope itself. This implies that the operator must be
syntactically distinct from the operators using dynamic $_. I imagine
something like

  lmap $t { $t + 1 } @​stuff

where $t is the topicaliser and the braces are mandatory. Defaulting the
topicaliser would look like

  lmap { $* + 1 } @​stuff

This can (and should) be prototyped on CPAN before going anywhere near
the core.

-zefram

@p5pRT
Copy link
Author

p5pRT commented Aug 16, 2013

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Aug 21, 2013

From aaron@priven.com

On Aug 15, 2013, at 6​:26 PM, Ricardo SIGNES (via RT) <perlbug-followup@​perl.org> wrote​:

We need to understand what would make this feature "salvaged," and then whether
it can be accomplished. If we can't figure out *any* acceptance criteria, then
the experiment seems doomed.

It seems to me that the problem that lexical $_ attempted to solve is where a called subroutine changes $_, but isn't supposed to.

  $_ = 'a';
  some_routine(@​args);
  print $_; # could be anything depending on what some_routine does

How do you allow some_routine to access $_ only when it is supposed to, but not when it's not?

I don't see how you do that without either

(a) putting extra code in the calling routine -- something like "call_without_exposing_topic some_routine(@​args)" -- which is easy to forget and adds nothing really over the existing "{ local $_; some_routine(@​args); }"

(b) putting extra code in the called routine -- something like "sub fred { my $_ = get_callers_lexical() ; do_something; }" -- which is, inherently, backwards-incompatible with all existing library code.

DWIM is great, but not when the computer has to be psychic.

So, the only way I can see to solve this problem is to create a new topic variable -- I'll call it $^_ but, you know, call it whatever you want -- that has to be either explicitly passed or explicitly taken, or both.

use feature 'lextopic';
# equivalent to "my $^_" and also now $^_ is used instead of $_

$^_ = "Something\n";
chomp;
# chomp is a built-in and uses the new topic, so $^_ is "Something"
new_routine();
# Now $^_ is "Anything"

sub new_routine {
  # $^_ is undefined
  callertopic;
  # Now $^_ is the caller's $^_,
  # or if caller wasn't running under feature 'lextopic', the global $_
  s/Some/Any/;
  return $^_;
}

use old_library ('old_routine');
topicalize { old_routine() };
# topicalize temporarily aliases $_ to $^_ in its block.
# Or, make a generic alias assignment operator and just do
# { local $_ := $^_ ; old_routine() }

If you don't either do "topicalize" or "callertopic", it defaults to *not* allowing access to the topic, which is safer than defaulting *to* sharing the topic, as global $_ does.

(I think $^_ might be a good name for the alternative topic variable, but I'm pretty sure callertopic and topicalize are the wrong names.)

I think that would work to solve the "this subroutine accidentally clobbered my $_" problem. I suspect the cure is worse than the disease.

--
Aaron Priven, aaron@​priven.com, www.priven.com/aaron

--
Aaron Priven, aaron@​priven.com, www.priven.com/aaron

@p5pRT
Copy link
Author

p5pRT commented Aug 21, 2013

From @ikegami

Isn't the lack of localisation in C<< while (<$fh>) >> the true problem?

@p5pRT
Copy link
Author

p5pRT commented Aug 21, 2013

From friedberg@exs.esb.com

Isn't this

DWIM is great, but not when the computer has to be psychic.

what DWIM really requires?

ROFLMAO (from a lurker)

Carl Friedberg
www.esb.com
The Elias Book of Baseball Records
2013 Edition

From​: Aaron Priven [mailto​:aaron@​priven.com]
Sent​: Wednesday, August 21, 2013 4​:02 PM
To​: perl5-porters@​perl.org Porters
Cc​: bugs-bitbucket@​rt.perl.org
Subject​: Re​: [perl #119315] [EXPERIMENT] the lexical topic, my $_

On Aug 15, 2013, at 6​:26 PM, Ricardo SIGNES (via RT) <perlbug-followup@​perl.org<mailto​:perlbug-followup@​perl.org>> wrote​:

We need to understand what would make this feature "salvaged," and then whether
it can be accomplished. If we can't figure out *any* acceptance criteria, then
the experiment seems doomed.

It seems to me that the problem that lexical $_ attempted to solve is where a called subroutine changes $_, but isn't supposed to.

  $_ = 'a';
  some_routine(@​args);
  print $_; # could be anything depending on what some_routine does

How do you allow some_routine to access $_ only when it is supposed to, but not when it's not?

I don't see how you do that without either

(a) putting extra code in the calling routine -- something like "call_without_exposing_topic some_routine(@​args)" -- which is easy to forget and adds nothing really over the existing "{ local $_; some_routine(@​args); }"

(b) putting extra code in the called routine -- something like "sub fred { my $_ = get_callers_lexical() ; do_something; }" -- which is, inherently, backwards-incompatible with all existing library code.

DWIM is great, but not when the computer has to be psychic.

So, the only way I can see to solve this problem is to create a new topic variable -- I'll call it $^_ but, you know, call it whatever you want -- that has to be either explicitly passed or explicitly taken, or both.

use feature 'lextopic';
# equivalent to "my $^_" and also now $^_ is used instead of $_

$^_ = "Something\n";
chomp;
# chomp is a built-in and uses the new topic, so $^_ is "Something"
new_routine();
# Now $^_ is "Anything"

sub new_routine {
  # $^_ is undefined
  callertopic;
  # Now $^_ is the caller's $^_,
  # or if caller wasn't running under feature 'lextopic', the global $_
  s/Some/Any/;
  return $^_;
}

use old_library ('old_routine');
topicalize { old_routine() };
# topicalize temporarily aliases $_ to $^_ in its block.
# Or, make a generic alias assignment operator and just do
# { local $_ := $^_ ; old_routine() }

If you don't either do "topicalize" or "callertopic", it defaults to *not* allowing access to the topic, which is safer than defaulting *to* sharing the topic, as global $_ does.

(I think $^_ might be a good name for the alternative topic variable, but I'm pretty sure callertopic and topicalize are the wrong names.)

I think that would work to solve the "this subroutine accidentally clobbered my $_" problem. I suspect the cure is worse than the disease.

--
Aaron Priven, aaron@​priven.com<mailto​:aaron@​priven.com>, www.priven.com/aaron<http​://www.priven.com/aaron>
--
Aaron Priven, aaron@​priven.com<mailto​:aaron@​priven.com>, www.priven.com/aaron<http​://www.priven.com/aaron>

@p5pRT
Copy link
Author

p5pRT commented Dec 17, 2017

From @cpansprout

This feature was removed in perl 5.24.0.

--

Father Chrysostomos

@p5pRT
Copy link
Author

p5pRT commented Dec 17, 2017

@cpansprout - Status changed from 'open' to 'rejected'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant