lexical $_

rafael on 2004-02-04T10:04:06

The new lexical $_ feature is in bleadperl since last night. More to come, as usual, in the P5P summary. (Which I didn't published this week, not out of laziness or something, but because very few things actually happened on P5P, besides the noise generated by evil mail worms. The next summary will cover two weeks.)


sub mylc { lc }

Juerd on 2004-02-04T12:10:43

Is there any way to get the caller's $_, like with Perl 6 $CALLER::_?

Re:sub mylc { lc }

rafael on 2004-02-04T12:29:09

Do you mean the caller's lexical $_, if it has one ?

Well, lexical $_ is no different from other lexical variables. So I imagine PadWalker will work with it.

If you write:
my $_; sub mylc { lc } then the lc will act on the lexical $_. (I.e. you'll have a closure.)

Re:sub mylc { lc }

Juerd on 2004-02-04T17:28:30

So the gap between built-ins and user defined functions gets even larger than it already is. With no clean way to access the caller's lexical $_ (PadWalker's nice, but not something I'd like to use on a regular basis) and built-ins that do work on that lexical $_, creating functions that work like built-ins gets hard.

Closures aren't good enough, because you can't import them and many people do like to have utility functions in modules.

The lexical $_ sounded like a good idea, but having a special variable that isn't really special is a bit weird, a bit like when you have a lexical $a or $b when sorting.

Perl 6 fixes this with the pseudo namespace CALLER::, which is the caller's MY::, the pseudo namespace for lexicals.

Re:sub mylc { lc }

rafael on 2004-02-04T18:23:39

A few points:

"my $_" is an addition, not a replacement. It's 100% backwards-compatible.

You can import closures, as long as they're not anonymous. But by doing so you "import" their lexicals as well.

What you want is (as I understand it) to define a function that defaults to $_, as in :

sub f(;$){my $arg = @_ ? $_[0] : $CALLER::_;...}

This is unrelated to the ability of my'ing $_, which is introduced to solve side-effect and scoping problems, as well as problems with "local $_" versus magic. May I point you a P5P for in-depth discussion of this...

Note: if you want to access the global $_, you can always write $::_ or (now) "our $_" (or simply $_ if there's no lexical $_ in scope.)

Re:sub mylc { lc }

Juerd on 2004-02-05T16:10:02

If I read p5p correctly, "lc" will still operate on the current $_, even if it is lexical.

But my contrived "mylc" would no longer work as with a global $_.
sub mylc { lc }
 
our $_ = "FOO";
print lc;    # foo
print mylc;  # foo
 
my $_ = "FOO";
print lc;    # foo
print mylc;  # FOO
The point of having a default variable is not having to type it! But you now have to pass it to "mylc" explicitly if it is lexical.

I understand that you want a lexical variable because you don't want other subs to mess with it. This action at a distance is unwanted and causes bugs. However, the action at a distance where $_ is used when no arguments are given, is a very useful tool. Larry realized that and invented $CALLER::_ for Perl 6.

I hope something like that (not requiring modules like PadWalker) will be in the Perl 5 that has lexical $_ support, or I fear it won't be as useful as the current $_. (After all, "local *_" fixes the magic stuff.)

Re:sub mylc { lc }

rafael on 2004-02-05T16:26:08

But my contrived "mylc" would no longer work as with a global $_. No, it will indeed. Just try it :) Look:

$ bleadperl -le 'sub f{print}$_=1;my$_=2;f'
1

Here f()'s body is not in a scope where a lexical $_ is defined. Hence it will not use it. Really the difference between $_ and my $_ is the same than the difference between $x and my $x. You don't need to learn new things. And this new feature doesn't make you loose anything.

Re:sub mylc { lc }

Juerd on 2004-02-05T19:30:46

Thank you for explaining how lexicals work. I am aware of scoping in Perl.

All I'm asking for is a cheat to get the $_ in the caller's lexical scope.

I am assuming that my $_ = 3; print; will actually output 3. Builtins often use $_ as the default value if no argument is given. My own utility functions also do that. I'd like to use lexical $_, but I'd also like to keep using utility functions the way I'm using builtins. Without scary stuff like PadWalker.

I'm not familiar with perl's guts, but is it hard to have Perl 6's pseudo-namespace CALLER:: in Perl 5? If it is, is it also hard to have just $CALLER::_?

$_ is the default variable. A lexical $_ that cannot act as the default variable would be very, very unperlish.

Because then you'd end up typing mylc($_) instead of simply mylc. And if you have to supply it yourself, what use is having a default variable?

But I think I'm not getting my point across. Maybe you're too excited about the change that you don't see my point, or maybe I'm just not clear enough.

Or maybe I'm the only one who thinks $_ should be and stay the default variable.

Re:sub mylc { lc }

rafael on 2004-02-05T19:59:15

Maybe you're too excited about the change that you don't see my point :) Thanks for your patience!

CALLER:: is feasible, I think it won't be difficult. So, assuming it gets implemented, the idiom to get the current default variable would be :

my $arg = exists $CALLER::{_} ? $CALLER::_ : $_;

This has the advantage of being valid in perl 5.8 and below. Assuming none of your modules is called CALLER.pm !

You're most welcome to post your thoughts to P5P. You definitively have a point about CALLER an d I'd like to see it discussed.