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

Re: Salvaging lexical $_ from deprecation

Thread Previous | Thread Next
From:
Ruslan Zakirov
Date:
February 20, 2013 14:48
Subject:
Re: Salvaging lexical $_ from deprecation
Message ID:
CAMOxC8vJNzkT=XaGZZBHzf3aUD51wjoD1ByKDQO9cxXNxqR5jg@mail.gmail.com
On Wed, Feb 20, 2013 at 4:46 PM, Aristotle Pagaltzis <pagaltzis@gmx.de> wrote:
> * Ruslan Zakirov <ruz@bestpractical.com> [2013-02-20 13:35]:
>> grep is a special function with (&@) prototype
>
> Only very notionally, not in any way in terms of how it really works.
>
>> but this prototype doesn't describe it completly. It doesn't tell
>> where to lookup $_ (and probably other variables) within the code
>> block binded to & in the protototype.
>
> The block in a `grep` is simply not a function. Consider what this does:
>
>     sub foo { grep { return; 1 } 1..4 }
>
> Then consider what this does:
>
>     use List::Util 'reduce';
>     sub foo { reduce { return; 1 } 1..4 }

You're right - lightweight blocks are not functions. This means that
builtin grep actually has prototype different from (&@). It is
something closer to ([{}s]@) where {} is for lightweight blocks and
"s" is for statements. sort for example has even trickier prototype
where first argument is optional, it's either block or a bareword
without comma after, so it's closer to ([{}b]?;@) where "b" is for
bareword and ? makes them optional. If we talk about implementing
builtin like functions in pure perl then all builtins should have
correct prototype that exactly express its arguments and dictates to
perl how to compile code that follows function name. In theory even
`if` and `else` can get a prototype :)

Should differences between lightweight blocks and functions influence
variables scoping? My previous ideas still stand. I just don't see how
mentioned difference between blocks and functions changes the fact
that prototypes at this moment lack ability to clarify where $_ comes
from within function and/or block that is passed into prototyped
function.

Well, one way forward is to implement "{}" prototype and make scoping
of $_ behave differently for "&" and "{}". So reduce can be
implemented in several ways:

1) sub reduce({};@) {...}

my $_ = 10;
reduce { ... } qw(foo bar); # valid
reduce sub { ... } qw(foo bar) # invalid
reduce \&foo, qw(foo bar) # invalid

2) reduce([{}&];@) { }

all of above valid, but $_ in second and third cases can suffer from
my $_; and will have to deal with it like in the following examples:

perl -E 'sub foo(&) { local $_ = 1; shift->() } my $_ = 10; foo sub { say $_ }'
10
perl -E 'sub foo(&) { local $_ = 1; shift->() } my $_ = 10; foo sub {
our $_; say $_ }'
1

This hardcoded difference makes it possible to get solution without
implementing my ":our($_)" idea. Less flexible, but can please all
camps after all.

Also, this whole thread misses the fact that $a and $b used in sort
fall into pretty much the same basket.

> (That difference is one of a number of reasons that Rafaƫl is wrong
> in his response to me that such lightweight blocks would be useless
> without lexical $_.)
>
>
> --
> Aristotle Pagaltzis // <http://plasmasturm.org/>

-- 
Best regards, Ruslan.

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