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

Re: Salvaging lexical $_ from deprecation

Thread Previous | Thread Next
From:
Jesse Luehrs
Date:
February 20, 2013 06:51
Subject:
Re: Salvaging lexical $_ from deprecation
Message ID:
20130220065137.GR23176@tozt.net
On Wed, Feb 20, 2013 at 07:42:21AM +0100, Rafael Garcia-Suarez wrote:
> On 20 February 2013 00:23, Ricardo Signes <perl.p5p@rjbs.manxome.org> wrote:
> > * Rafael Garcia-Suarez <rgs@consttype.org> [2013-02-19T16:07:08]
> >> I notice that the lexical topicalizer "my $_" is deprecated in blead.
> >> At this point I assume that the reasons for the deprecation given in
> >> perl5177delta are exhaustive. All those reasons are pointing to
> >> implementation problems, notably at the XS interface level, which can
> >> be solved; there are no reasons given that pertain to language design
> >> issues.
> >
> > The reasons I find more compelling are those that Jesse L. mentioned.  How do
> > you suppose that the language is supposed to work, there?
> >
> >> In conclusion: think first about language design; think about having a
> >> vision for the future. Don't throw away language features just because
> >> they introduce difficult bugs you'd rather sweep under the rug.
> >> Deprecating $_ is laziness and impatience of the worst kind; do not
> >> forget to also display hubris, because only hubris makes the future
> >> promises shine.
> >
> > I *am* thinking about language design.  The bugs that interest me are the ones
> > that will be written by users, in Perl, because of the language design.  I
> > don't see how it can be made to make sense or become valuable.
> >
> > What *should* this program print?
> >
> >   use 5.12.0;
> >   my ($A, $B, $C, $D, $E);
> >
> >   {
> >     my $_ = "foo";
> >
> >     $A = sub { say "A" if       /foo/ };
> >     $B = sub { say "B" if $_ =~ /foo/ };
> >     $C = sub { say "C" if grep { /foo/ } qw(bar) };
> >     $D = sub { say "D" if grep { (sub { $_ =~ /foo/})->() } qw(bar) };
> >     $E = sub { say "E" if (sub { $_ =~ /foo/ })->() };
> >   }
> >
> >   local $_ = "bar";
> >   $A->();
> >   $B->();
> >   $C->();
> >   $D->();
> >   $E->();
> 
> This program should print A, B, and E, given that grep in C and D is
> using $_ as an iteration variable. And actually it does. This is also
> what it will do if you replace $_ by a more mundane "my $x" in A, B
> and E.

And this is exactly what breaks things. How is B any different from
something like

  my $_ = ...;
  # ...
  try {
      require Foo;
  }
  catch {
      die $_ unless /Can't locate .* in \@INC/;
  }

This will not work as expected, because the catch block will close over
the lexical $_. This catches people up very regularly, I've received
many, many bug reports about it. How can we resolve this? Currently,
perl does not make any distinction between "foo(sub { ... })" and
"foo { ... }" (if foo in the second case is declared with a prototype of
(&)). How then do we write user-defined things that behave like map or
grep in terms of how they interact with $_?

-doy

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About