Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Lexical $_ means we need $CALLER::_

3 views
Skip to first unread message

Juerd

unread,
Feb 6, 2004, 11:44:38 AM2/6/04
to perl5-...@perl.org
Dear porters,

After some discussion at http://use.perl.org/~rafael/journal/17203,
Rafael asked me to share my thoughts on p5p.

I outlined my post and then wrote some POD from it, with code examples,
only to find out that the outlining software I used didn't autosave. It
segfaulted and my POD was gone.

An older version of the file still contains the outline without the POD.
I'm going to annoy you with the raw outline, hoping it'll make some
sense, because I don't have the time to write everything again.

If the outline is verbose enough, please let me know. If it isn't, I'll
post the full version in a week or two.


Introduction

- Perl has a default variable

- The default variable is useful

- User defined subs can also have this feature


The Global $_

- Everyone knows globals are Evil

- Action at a distance (AaaD) (MJD's example with tie)

- Sometimes AaaD is wanted: user defined subs that default to $_

- local $_ doesn't even fix it (perlvar, beginning perl), local *_ does (MJD)


The Lexical $_

- Other subs cannot see it

- AaaD bugs fixed

- Nice speed improvement

- Problem: sometimes you *want* AaaD, mainly with $_

- Default only for builtin operators makes no sense in our Perl world


Perl 6 Story (A6)

- $_ is lexical by default

- Every sub has its own implicitly declared $_

- $CALLER::_ fixes problem


Perl >5.8 Story

- $_ is global by default

- $_ can be made lexical by explicity my'ing it

- No fix for problem :(


A Better Perl 5 Story

- We do what Perl 6 does

- Perl 5 gets a CALLER:: pseudo-package

- Backwards compatibility is free:

- exists $CALLER::{_} ? $CALLER::_ : $::_

- *CALLER::_{SCALAR} || \$::_ allows for lexical @_

- package Compat::CALLER::_; sub import { *CALLER::_ = *::_ if $] < ... } 42

Regards,

Juerd

Michael G Schwern

unread,
Feb 6, 2004, 3:15:49 PM2/6/04
to Juerd, perl5-...@perl.org
On Fri, Feb 06, 2004 at 05:44:38PM +0100, Juerd wrote:
> Perl >5.8 Story
>
> - $_ is global by default
>
> - $_ can be made lexical by explicity my'ing it
>
> - No fix for problem :(

You forget, $_ is the globalest of all globals. It always resides in main.

package Foo;
$_ = 42;

package Bar;
print $::_;


--
Michael G Schwern sch...@pobox.com http://www.pobox.com/~schwern/
11. Every old idea will be proposed again with a different name and
a different presentation, regardless of whether it works.
-- RFC 1925

Michael G Schwern

unread,
Feb 6, 2004, 4:27:52 PM2/6/04
to Juerd, perl5-...@perl.org
On Fri, Feb 06, 2004 at 09:29:50PM +0100, Juerd wrote:
> Michael G Schwern skribis 2004-02-06 12:15 (-0800):

> > On Fri, Feb 06, 2004 at 05:44:38PM +0100, Juerd wrote:
> > > Perl >5.8 Story
> > > - $_ is global by default
> > > - $_ can be made lexical by explicity my'ing it
> > > - No fix for problem :(
> > You forget, $_ is the globalest of all globals. It always resides in main.
>
> I'm not sure which you should read: "Coping with Scoping"[1] or Rafael's
> message about the new lexical $_ [2] :)
>
> The point about the lexical $_ is that it is *not* global. A sub cannot
> access its caller's lexical $_ unless something allows it to.
> PadWalker[3] is a possibility, but I'd rather not use that in production
> code.

I've read Rafael's lexical $_ proposal. I believe we have a misunderstanding.
Here's what I take to be your problem.

$_ = 42;
{
my $_ = 23;

# Problem: print the global $_, not the lexical, so that
# 42 is printed.
}

If that is your problem, here is your solution.

$_ = 42;
{
my $_ = 23;
print $::_;
}

Same as you would write...

$foo = 42;
{
my $foo = 23;
print $::foo;
}

..except that the global $_ is always in package main so there's no need to
know your caller in order to name it explicitly. $::_ is always going to give
you the global $_. If I understand the problem correctly, this obviates the
need for $CALLER::_.

Never underestimate the bandwidth of a mag tape on a bicycle.
-- Carl Friedberg in
<04716E70DA1C6046BEC...@babbage.esb.com>

Michael G Schwern

unread,
Feb 6, 2004, 5:18:08 PM2/6/04
to Juerd, perl5-...@perl.org
On Fri, Feb 06, 2004 at 11:01:44PM +0100, Juerd wrote:
> Michael G Schwern skribis 2004-02-06 13:27 (-0800):

> > I've read Rafael's lexical $_ proposal. I believe we have a
> > misunderstanding.
> > Here's what I take to be your problem.
> > $_ = 42; { my $_ = 23; # Problem: print the global $_, not the lexical, so that 42 is printed.

> > }
> > If that is your problem, here is your solution.
>
> It's not.
>
> My problem is that only builtins can access lexical $_ as the default
> variable with the current patch. Subs you create yourself can't use it,

Ok, now I understand. However, this makes sense to me. Its lexical.
But I see your point, it would be nice if user subs could act like built-ins.

Now that I understand, a general purpose CALLER pseudo-package seems a good
idea. There's lots one can do with that beyond simply $_ and it solves a
lot of "I'd love to put this into a module but then I'd be in the wrong scope"
problems.

Well, my work here is done. If you need me again, just admit that you're
screwed and die.

h...@crypt.org

unread,
Feb 7, 2004, 8:16:43 AM2/7/04
to Michael G Schwern, Juerd, perl5-...@perl.org
Michael G Schwern <sch...@pobox.com> wrote:
:Now that I understand, a general purpose CALLER pseudo-package seems a good
:idea. There's lots one can do with that beyond simply $_ and it solves a
:lot of "I'd love to put this into a module but then I'd be in the wrong scope"
:problems.

It does however raise a host of new questions and potential new problems
I think. %{CALLER::} gives you something effectively akin to TCL's
'uplevel', and greatly changes our old model with regard to the visibility
of lexicals.

Not that this is a reason not to do it, just a heads up that there are
ramifications.

Hugo

Juerd

unread,
Feb 6, 2004, 3:29:50 PM2/6/04
to Michael G Schwern, perl5-...@perl.org
Michael G Schwern skribis 2004-02-06 12:15 (-0800):

> On Fri, Feb 06, 2004 at 05:44:38PM +0100, Juerd wrote:
> > Perl >5.8 Story
> > - $_ is global by default
> > - $_ can be made lexical by explicity my'ing it
> > - No fix for problem :(
> You forget, $_ is the globalest of all globals. It always resides in main.

I'm not sure which you should read: "Coping with Scoping"[1] or Rafael's


message about the new lexical $_ [2] :)

The point about the lexical $_ is that it is *not* global. A sub cannot
access its caller's lexical $_ unless something allows it to.
PadWalker[3] is a possibility, but I'd rather not use that in production
code.

Perl 6 deals with this problem by introducing a CALLER::
pseudo-package[4].

I believe that is what Perl 5 should also do if lexical $_ is indeed
introduced.


Juerd

[1] http://perl.plover.com/FAQs/Namespaces.html
[2] http://www.nntp.perl.org/group/perl.perl5.porters/88225
[3] http://search.cpan.org/perldoc?PadWalker (unreachable now)
[4] http://www.perl.com/lpt/a/2003/03/07/apocalypse6.html

Juerd

unread,
Feb 6, 2004, 5:01:44 PM2/6/04
to Michael G Schwern, perl5-...@perl.org
Michael G Schwern skribis 2004-02-06 13:27 (-0800):

> I've read Rafael's lexical $_ proposal. I believe we have a
> misunderstanding.
> Here's what I take to be your problem.
> $_ = 42; { my $_ = 23; # Problem: print the global $_, not the lexical, so that 42 is printed.

> }
> If that is your problem, here is your solution.

It's not.

My problem is that only builtins can access lexical $_ as the default
variable with the current patch. Subs you create yourself can't use it,

making the gap between builtins and user defined subs even larger.

sub lcfirstvowel (;$) {
my $dummy = @_ ? shift : $_;
$dummy =~ s/([aoeui])/\l$1/i;
return $dummy;
}

$_ = "HELLO WORLD";
print lcfirstvowel $_; # HeLLO WORLD
print lcfirstvowel; # HeLLO WORLD

my $_ = "TIMTOWTDI";
print lcfirstvowel $_; # TiMTOWTDI
print lcfirstvowel; # HeLLO WORLD

It makes sense that it works this way. Consider this Perl 6 snippet:

sub lcfirstvowel (?$str is copy = $_) {
$str ~~ s/:i (<vowel>) /\l[$1]/;
return $str;
}

$_ = "LEXICAL";
print lcfirstvowel $_; # LeXICAL
print lcfirstvowel; # empty string because &lcfirstvowel has its
# own $_, which is undef. That value gets
# stringified by the s///.

To allow &lcfirstvowel to work like a built in function, CALLER:: exists
to let it use the *caller*'s lexical $_.

sub lcfirstvowel (?$str is copy = $CALLER::_) {
$str ~~ s/:i (<vowel>) /\l[$1]/;
return $str;
}

$_ = "STILL LEXICAL";
print lcfirstvowel $_; # STiLL LEXICAL
print lcfirstvowel; # STiLL LEXICAL # eureka!

CALLER:: is needed when $_ can be a lexical. Otherwise user defined subs
can no longer use this useful Perlish feature (defaulting to $_). One
would write something like:

sub lcfirstvower (;$) {
my $dummy = ${ @_ ? \shift : *CALLER::_{SCALAR} || \$::_ };

# or:
my $dummy = @_ ? shift : (exists $CALLER::{_} ? $CALLER::_ : $::_);

# or: [1]
use Compat::CALLER::_;
my $dummy = $CALLER::_;

$dummy =~ s/([aoeui])/\l$1/i;
return $dummy;
}

my $_ = "YAY";
print lcfirstvowel; # YaY

> $_ = 42; { my $_ = 23; print $::_; }

> ...


> you the global $_. If I understand the problem correctly, this obviates the
> need for $CALLER::_.

No, that's Perl 6's OUTER:: (apo 4), I'm talking about CALLER:: (apo 6).

I don't think OUTER:: is needed at all. I even think it's better to not
have it.

CALLER has to do with a sub that is called. CALLER:: is needed to enable
defaulting to a lexical $_ like builtins do.

Juerd

Juerd

unread,
Feb 6, 2004, 5:39:05 PM2/6/04
to Michael G Schwern, perl5-...@perl.org
Michael G Schwern skribis 2004-02-06 14:18 (-0800):

> On Fri, Feb 06, 2004 at 11:01:44PM +0100, Juerd wrote:
> > My problem is that only builtins can access lexical $_ as the default
> > variable with the current patch. Subs you create yourself can't use it,
> Ok, now I understand. However, this makes sense to me. Its lexical.
> But I see your point, it would be nice if user subs could act like built-ins.
>
> Now that I understand, a general purpose CALLER pseudo-package seems a good
> idea. There's lots one can do with that beyond simply $_ and it solves a
> lot of "I'd love to put this into a module but then I'd be in the wrong scope"
> problems.

CALLER:: would be nice in any case, but it's *needed* if $_ can be
lexical and we want Perl to stay Perlish :)

By the way, eval EXPR has a nice feature: if the current package is in B::,
it evals in the caller's context.

package B::Foo;

sub main::lcfirstvowel (;$) {
my $dummy = @_ ? shift : eval '$_';
$dummy =~ s/.../.../;
return $dummy;
}

package main;

my $_ = 'CAMEL';
print lcfirstvowel; # CaMEL

But I think that's not something we want everyone to use :)

By the way - my messages don't seem to be delivered to p5p subscribers.
Any idea why? Your replies do show up in the nntp web interface, but
only my first message in this thread is there.


Juerd

Juerd

unread,
Feb 7, 2004, 9:39:40 AM2/7/04
to sch...@pobox.com, perl5-...@perl.org
Juerd skribis 2004-02-06 23:01 (+0100):

> # or: [1]
> use Compat::CALLER::_;
> my $dummy = $CALLER::_;

[1] Only possible if CALLER:: can also get the caller's global variables
if that happens to be the effective declaration. Apocalypse 6 says it's
for lexicals only, but that would be a problem in Perl 5, where $_
can of course still be a global, even when a lexical one exists:

sub foo { $CALLER::_ || $_ }

my $_ = "bar";
print foo; # bar
our $_ = "baz";
print foo; # bar # (!)

Unless the "our" declaration makes the lexical go away completely. I
don't know what perl does and if that'll stay that way.


Juerd

Abigail

unread,
Feb 12, 2004, 5:33:48 PM2/12/04
to Juerd, Michael G Schwern, perl5-...@perl.org
On Fri, Feb 06, 2004 at 11:39:05PM +0100, Juerd wrote:
> Michael G Schwern skribis 2004-02-06 14:18 (-0800):
> > On Fri, Feb 06, 2004 at 11:01:44PM +0100, Juerd wrote:
> > > My problem is that only builtins can access lexical $_ as the default
> > > variable with the current patch. Subs you create yourself can't use it,
> > Ok, now I understand. However, this makes sense to me. Its lexical.
> > But I see your point, it would be nice if user subs could act like built-ins.
> >
> > Now that I understand, a general purpose CALLER pseudo-package seems a good
> > idea. There's lots one can do with that beyond simply $_ and it solves a
> > lot of "I'd love to put this into a module but then I'd be in the wrong scope"
> > problems.
>
> CALLER:: would be nice in any case, but it's *needed* if $_ can be
> lexical and we want Perl to stay Perlish :)


I fail to see a problem that needs to be fixed. I use lexical variables
if I *don't* want the variable to be visible outside of its defining
scope. So, if I do 'my $_ = "foo"; bar ();' I would not expect 'bar'
to be able to see $_. If I would, I wouldn't have made $_ lexical.

Furthermore, by introducing this CALLER pseudo-package, aren't we just
reintroducing the same problem that 'my $_' is trying to fix?

Abigail

Abigail

unread,
Feb 12, 2004, 6:44:03 PM2/12/04
to Juerd, perl5-...@perl.org
On Fri, Feb 13, 2004 at 12:19:22AM +0100, Juerd wrote:
> Abigail skribis 2004-02-12 23:33 (+0100):

> > I fail to see a problem that needs to be fixed. I use lexical variables
> > if I *don't* want the variable to be visible outside of its defining
> > scope. So, if I do 'my $_ = "foo"; bar ();' I would not expect 'bar'
> > to be able to see $_. If I would, I wouldn't have made $_ lexical.
>
> In other words, with
> my $_ = "foo\n";
> chomp;
> you wouldn't expect 'chomp' to be able to see $_?

I don't expect 'chomp' to "see" $_. I do however chomp to modify $_.

> Or is 'bar' much different from 'chomp'? I think expectations should be
> the same for builtins and your own subs.

But they aren't the same. Witness:

$ perl -MO=Deparse -e 'chomp'
chomp $_;
$

'chomp' doesn't "see" $_. It gets passed on implicitely.

How are you going to that for 'bar'?

> By the way, any defaulting to $_ should always be documented.
> Documentation should change your expectations.
>
> I like having little subs that work like builtins. These are mainly used
> when they're much like an existing function. Protypes are handy to allow
> special syntax, but they can't let me access your lexical $_.

And they shouldn't.

> > Furthermore, by introducing this CALLER pseudo-package, aren't we just
> > reintroducing the same problem that 'my $_' is trying to fix?
>

> No, not at all. The lexical $_ is trying to fix *accidental* action at a
> distance. Sometimes, action at a distance is wanted and very handy.

Yeah, you think now that CALLER is very handy. Introduce it, and a few
years down the road, all functions that defaulted to $_ will now default
to $CALLER::_ - the sign of a 'good' programmer, he takes into account
$_ might lexical.

By then, we have the same problem as we have now. $_ is once again
unhidable.

> CALLER:: is going to happen anyway. If not in Perl 5, then we'll have to
> wait for Perl 6. If lexical $_ happens now, I also want CALLER:: now.

Let's deal with Perl 6 if it comes. It's been over 3.5 years now, and
Larry is still working on the language design. I retire in 25 years.
I expect my retirement to happen before perl6.

> Having a default variable is useless if your subs can't default to it!

Yes, I think subs should be able to default to $_. But I don't think
scopes should be able to reach into other scopes and pull lexicals
out of them. A pseudo-package CALLER is going to do a *lot* more than
implicitely passing $_ as an argument if none given.


Abigail

Mark Jason Dominus

unread,
Feb 12, 2004, 10:49:18 PM2/12/04
to perl5-...@perl.org

I'm with Abigail on this. The whole point of lexical variables is
that they are private, and you don't have to worry that code in some
other scope is going to tamper with them. The whole point of
declaring $_ with 'my' is so that it becomes private, and you don't
have to worry that code in some other scope is going to tamper with
it. Now Juerd wants to introduce this awful CALLER:: idea, which
wrecks lexical variables. If CALLER:: is a good idea, then 'my $_'
isn't.

Perl originally had all global variables. That turned out to be a
problem, because functions large programs had poor encapsulation. In
Perl 5, 'my' was introduced to solve this problem; now functions could
have private variables.

Now Juerd wants 'CALLER::'. So I guess in another few years we can
introduce a new kind of variable that is 'really truly private',
inaccessible even to the CALLER:: mechanism.

Juerd's feature is already availble for people who really want it. It
is available via XS, and it is available via the Padwalker module. I
think that that is exactly where that feature belongs.

Rafael Garcia-Suarez

unread,
Feb 13, 2004, 3:37:10 AM2/13/04
to perl5-...@perl.org
Mark Jason Dominus wrote in perl.perl5.porters :

>
> Now Juerd wants 'CALLER::'. So I guess in another few years we can
> introduce a new kind of variable that is 'really truly private',
> inaccessible even to the CALLER:: mechanism.

Good point. However, Juerd doesn't really want CALLER:: ; he wants
some syntax handiness so he can declare functions foo() which, when
invoked as
foo;
are actually parsed as
foo($_);
(where $_ is lexical or not, depending on whether there's a lexical
$_ in the current scope.)

You're just saying that CALLER:: is overkill for that purpose.
Actually, a prototype might do as well (just throwing random ideas) :
sub foo($$_);
meaning "foo takes 3 arguments, the last one being optional and
defaulting to $_". After all, one of the purposes of prototypes
is to mimic built-ins.

Juerd

unread,
Feb 12, 2004, 6:19:22 PM2/12/04
to Abigail, Juerd, Michael G Schwern, perl5-...@perl.org
Abigail skribis 2004-02-12 23:33 (+0100):
> I fail to see a problem that needs to be fixed. I use lexical variables
> if I *don't* want the variable to be visible outside of its defining
> scope. So, if I do 'my $_ = "foo"; bar ();' I would not expect 'bar'
> to be able to see $_. If I would, I wouldn't have made $_ lexical.

In other words, with


my $_ = "foo\n";
chomp;

you wouldn't expect 'chomp' to be able to see $_?

Or is 'bar' much different from 'chomp'? I think expectations should be
the same for builtins and your own subs.

By the way, any defaulting to $_ should always be documented.


Documentation should change your expectations.

I like having little subs that work like builtins. These are mainly used
when they're much like an existing function. Protypes are handy to allow
special syntax, but they can't let me access your lexical $_.

> Furthermore, by introducing this CALLER pseudo-package, aren't we just


> reintroducing the same problem that 'my $_' is trying to fix?

No, not at all. The lexical $_ is trying to fix *accidental* action at a


distance. Sometimes, action at a distance is wanted and very handy.

CALLER:: is going to happen anyway. If not in Perl 5, then we'll have to


wait for Perl 6. If lexical $_ happens now, I also want CALLER:: now.

Having a default variable is useless if your subs can't default to it!


Juerd

Juerd

unread,
Feb 13, 2004, 4:45:47 AM2/13/04
to Abigail, perl5-...@perl.org
Abigail skribis 2004-02-13 0:44 (+0100):

> > In other words, with
> > my $_ = "foo\n";
> > chomp;
> > you wouldn't expect 'chomp' to be able to see $_?
> I don't expect 'chomp' to "see" $_. I do however chomp to modify $_.

See, read, access, mutate, modify. In this case, all the same.

> But they aren't the same. Witness:
> $ perl -MO=Deparse -e 'chomp'
> chomp $_;
> $
> 'chomp' doesn't "see" $_. It gets passed on implicitely.
> How are you going to that for 'bar'?

You can't. It would be great to have a prototype that allows this, but
that would probably be hard to do, since prototypes don't do that kind
of thing in Perl 5.

So there isn't a way to do exactly what builtins do, but it would be
nice to have a workaround for that problem so that existing code that
defaults to $_ can be changed and new can be created, without it doing
weird things when the caller happens to have a lexical $_.

I do consider it accessing a global $_ when the caller has a lexical $_
"weird".

> > I like having little subs that work like builtins. These are mainly used
> > when they're much like an existing function. Protypes are handy to allow
> > special syntax, but they can't let me access your lexical $_.
> And they shouldn't.

Then please don't use my code, because I disagree.

> > No, not at all. The lexical $_ is trying to fix *accidental* action at a
> > distance. Sometimes, action at a distance is wanted and very handy.
> Yeah, you think now that CALLER is very handy. Introduce it, and a few
> years down the road, all functions that defaulted to $_ will now default
> to $CALLER::_ - the sign of a 'good' programmer, he takes into account
> $_ might lexical.
>
> By then, we have the same problem as we have now. $_ is once again
> unhidable.

That is not the problem as we have now.

The problem is that code changes *ACCIDENTALLY* uses someone else's $_.

When a sub defaults to $_ and is documented to do that, it is not an
accident and the behaviour is wanted.

Lexicals aren't there to *hide* variables, they exist to make
programming easier by eliminating accidental access and by cleaning up
automatically.

See PadWalker.

> [pessimist Perl 6 view]

Not the right place for this, imho.

> > Having a default variable is useless if your subs can't default to it!
> Yes, I think subs should be able to default to $_. But I don't think
> scopes should be able to reach into other scopes and pull lexicals
> out of them.

They are already able to. I'm just asking for a built in and easier way.

> A pseudo-package CALLER is going to do a *lot* more than implicitely
> passing $_ as an argument if none given.

It doesn't *do* anything. It gets used. You use it if you like it, you
don't use it if you don't like it. You can choose.

But whatever whoever's choice is regarding the use of CALLER::, it does
not introduce strange, unexpected bugs or un-fix the problem with $_.
Every access of a lexical in the caller's scope is explicit.


If you want "security" for variables, that is a completely different
discussion. It would require a new pragma and a way to make PadWalker
and CALLER:: not be able to see/access/whatever your lexicals.


Juerd

Rafael Garcia-Suarez

unread,
Feb 13, 2004, 5:20:39 AM2/13/04
to Juerd, abi...@abigail.nl, perl5-...@perl.org
Juerd wrote:
> > But they aren't the same. Witness:
> > $ perl -MO=Deparse -e 'chomp'
> > chomp $_;
> > $
> > 'chomp' doesn't "see" $_. It gets passed on implicitely.
> > How are you going to that for 'bar'?
>
> You can't. It would be great to have a prototype that allows this, but
> that would probably be hard to do, since prototypes don't do that kind
> of thing in Perl 5.

That's not my opinion, at a first glance.

> When a sub defaults to $_ and is documented to do that, it is not an
> accident and the behaviour is wanted.

But there's still a problem.

my_sub($_); # pass $_ by value -- can't modify it
my_sub(); # if fetches $_, if can modify it.

What you want in fact is a \_ prototype.

> If you want "security" for variables, that is a completely different
> discussion. It would require a new pragma and a way to make PadWalker
> and CALLER:: not be able to see/access/whatever your lexicals.

Arms race !

Juerd

unread,
Feb 13, 2004, 6:52:56 AM2/13/04
to Rafael Garcia-Suarez, perl5-...@perl.org
Rafael Garcia-Suarez skribis 2004-02-13 11:20 (+0100):

> But there's still a problem.
> my_sub($_); # pass $_ by value -- can't modify it
> my_sub(); # if fetches $_, if can modify it.

Que?

sub chompish { $_[0] =~ s/o$// }
my $lexical = "foo";
chompish $lexical; # pass by value?!
print $lexical; # fo


A scalar is a scalar. It can be readonly, but passing a scalar doesn't
make it that.

Juerd

Abigail

unread,
Feb 15, 2004, 6:01:59 PM2/15/04
to david nicol, Juerd, Perl 5 Porters
On Sun, Feb 15, 2004 at 04:52:36PM -0600, david nicol wrote:
>
> > > > Furthermore, by introducing this CALLER pseudo-package, aren't we just
> > > > reintroducing the same problem that 'my $_' is trying to fix?
> > >
> > > No, not at all. The lexical $_ is trying to fix *accidental* action at a
> > > distance. Sometimes, action at a distance is wanted and very handy.
> >
> > Yeah, you think now that CALLER is very handy. Introduce it, and a few
> > years down the road, all functions that defaulted to $_ will now default
> > to $CALLER::_ - the sign of a 'good' programmer, he takes into account
> > $_ might lexical.
> >
> > By then, we have the same problem as we have now. $_ is once again
> > unhidable.
>
> I hadn't realized that the point of C<my $_> was to allow _hiding_ the
> default variable. It seems to me that if you want to hide your variable,
> don't use the default variable.
>
> The issue I thought we are trying to solve here is _clobbering_ the
> default variable. Which good perl programmers now avoid by localizing
> $_ and they've been doing that I don't know how long. Since the introduction
> of the C<local> keyword.
>
> Maybe what is needed is rewriting of C<local> that addresses whatever issues
> exist with C<local>?
>
> As I understand it C<local> does this, and all at run time:
>
> create a handler that will replace the current glob into
> the symbol table on scope exit, and holds an alias to the current glob
>
> clobber the current entry in the symbol table with a fresh new glob
>
> at scope exit time (including exit from scope via C<goto>), run the handler
>
>
> while C<my> does this, and all at compile time:
>
> extend the current scope's pad
>
> note to the compiler that further reference to variables of the
> provided name within the current scope mean reference to the
> element in the pad
>
> note the mapping permanently in case we have to C<eval> something
> in this scope later; throw away the mapping when there was
> no C<eval> in the scope
>
>
> If we get %CALLER:: which refers to the last lexical-scope we were in
> before getting called, we would never get to throw away any pad name
> mapping tables (I'm guessing at terminology) because function calls are
> all by-name and run-time-bound so they can be replaced with something that
> does an eval.
>
>
> What if we special-case C<my $_> to really work like C<local $_> but
> with a special "default stack" that skips the symbol table?
>
> Then
>
> my $_
>
> would not be an error anymore, and $_ is still available to you and
> your callees, and you don't need to clutter up your sleek, modern
> code with that confusing relic C<local>.


The availability of %CALLER means that

$CALLER::_ = "foo";

is clobbering your lexical $_, precisely what you give as a reason
for the existance of

my $_

in the first place.


Requiring access to the lexical scope of whatever is calling us in
order to mimic buildins that act on $_ by default is an example of
an "X-Y" problem. To solve X, we think we need Y, so we ask for a way
to do Y. But what we really want is having $_ (either the current
lexical, or $main::_) passed as an implicite argument if no arguments
are given. That's how Deparse parses 'chomp', and that's how you should
get access. It even makes that the code of your subroutines is simpler,
as you don't have create a special case for @_ == 0.


Abigail

Mark Jason Dominus

unread,
Feb 15, 2004, 6:19:01 PM2/15/04
to Perl 5 Porters
david nicol <what...@davidnicol.com>:

> As I understand it C<local> does this, and all at run time:
>
> create a handler that will replace the current glob into
> the symbol table on scope exit, and holds an alias to the current glob
>
> clobber the current entry in the symbol table with a fresh new glob


Not exactly.

local *foo;

does that, but

local $foo;

does not. It does not change the glob at all. It fetches the value
of $foo, creates a handler that will restore this value $foo (by
assignment) at scope exit, and assigns undef to $foo.

Witness:


tie $foo => 'Ouch';
sub Ouch::TIESCALAR { bless [] => "Ouch" }
sub Ouch::FETCH { print "FETCH\n"; return 119 }
sub Ouch::STORE { print "STORE $_[1]\n" }

func();
sub func {
local $foo;
$foo = 12;
}

Thie emits:

FETCH
STORE
STORE 12
STORE 119

The 'local' is performing an implicit <FETCH> and <STORE undef> on
'$foo'; the cleanup action is performing an implicit <STORE 119>.

This means that 'local $foo' is not actually safe for localizing the
global variable '$foo' inside a function. $foo might have been tied,
and the function might be performing an arbitrarily destructive action
by localizing it.

The situation is further complicated by:

tie $foo => 'Ouch';
sub Ouch::TIESCALAR { bless [] => "Ouch" }
sub Ouch::FETCH { print "FETCH\n"; return 119 }
sub Ouch::STORE { print "STORE $_[1]\n" }

for ($foo, $bar) {
func();
}

sub func {
local $_;
$_ = 12;
}

Here func() does 'local $_', and the FETCH and STORE actions are
invoked even though $_ was never explicitly tied.

Almost any function that does "local $_" is erroneous and might fail
in an arbitrarily destructive way, depending on unrelated details of
the program in which it is embedded.


Dave Mitchell

unread,
Feb 15, 2004, 6:49:52 PM2/15/04
to david nicol, Abigail, Juerd, Perl 5 Porters
On Sun, Feb 15, 2004 at 04:52:36PM -0600, david nicol wrote:
> while C<my> does this, and all at compile time:
>
> extend the current scope's pad
>
> note to the compiler that further reference to variables of the
> provided name within the current scope mean reference to the
> element in the pad
>
> note the mapping permanently in case we have to C<eval> something
> in this scope later; throw away the mapping when there was
> no C<eval> in the scope

This does not happen; the pad "mapping" is not thrown away, even in the
absence of evals.

Also, my has a run-time action, which is place an instruction on the
savestack to free the lexical's SV on scope exit.

> If we get %CALLER:: which refers to the last lexical-scope we were in
> before getting called, we would never get to throw away any pad name
> mapping tables (I'm guessing at terminology) because function calls are
> all by-name and run-time-bound so they can be replaced with something that
> does an eval.

This is irrelevant since the pad names are not dropped.

> What if we special-case C<my $_> to really work like C<local $_> but
> with a special "default stack" that skips the symbol table?

Lets not.

--
"Emacs isn't a bad OS once you get used to it.
It just lacks a decent editor."

Ton Hospel

unread,
Feb 15, 2004, 8:16:01 PM2/15/04
to perl5-...@perl.org
In article <200402152319...@plover.com>,

Mark Jason Dominus <m...@plover.com> writes:
> Almost any function that does "local $_" is erroneous and might fail
> in an arbitrarily destructive way, depending on unrelated details of
> the program in which it is embedded.

Which is why I consider the fact that magic works on variables
instead of values a perl (design) bug.

Mark Jason Dominus

unread,
Feb 15, 2004, 9:46:38 PM2/15/04
to perl5-...@perl.org
perl5-...@perl.org:

On the other hand, if it worked on values and not variables, then

local $/ = "W";

would not affect the value of the magic $/ variable.

It's a tricky problem.

Juerd

unread,
Feb 15, 2004, 6:25:15 PM2/15/04
to Abigail, perl5-...@perl.org
Abigail skribis 2004-02-16 0:01 (+0100):

> to do Y. But what we really want is having $_ (either the current
> lexical, or $main::_) passed as an implicite argument if no arguments
> are given. That's how Deparse parses 'chomp', and that's how you should
> get access. It even makes that the code of your subroutines is simpler,
> as you don't have create a special case for @_ == 0.

If it would be possible to really do default to $_ in that way, that
would certainly fix the problem I described. It would also not stand in
the way of optimizations, and yes, code would probably become clearer.

However, Perl 6 is going to have CALLER::, and I think it is a good idea
to implement it now. It not only fixes the problem, but also allows for
creative use that we have probably not even thought of yet.

I guess a prototype or attribute that allows to get $_ passed implicitly
would (if possible) be better than teaching people to use $CALLER::_.
But still, I think having CALLER:: would be nice. It appears we have two
different discussions now :)


Juerd

Juerd

unread,
Feb 15, 2004, 7:37:14 PM2/15/04
to david nicol, perl5-...@perl.org
david nicol skribis 2004-02-15 17:58 (-0600):
> On Sun, 2004-02-15 at 17:26, Juerd wrote:
> > Why just as the last one? See substr.
> What part of substr deals with the default variable? Substr has

Ehm. I don't know why I typed substr when I meant split. Sorry for the
confusion.


Juerd

David Nicol

unread,
Feb 15, 2004, 6:18:57 PM2/15/04
to Abigail, Juerd, Perl 5 Porters
On Sun, 2004-02-15 at 17:01, Abigail wrote:

> Requiring access to the lexical scope of whatever is calling us in
> order to mimic buildins that act on $_ by default is an example of
> an "X-Y" problem. To solve X, we think we need Y, so we ask for a way
> to do Y. But what we really want is having $_ (either the current
> lexical, or $main::_) passed as an implicite argument if no arguments
> are given. That's how Deparse parses 'chomp', and that's how you should
> get access. It even makes that the code of your subroutines is simpler,
> as you don't have create a special case for @_ == 0.
>
>
> Abigail

Ah. Yes. You are right. Let's add underscore to characters that make
sense in prototypes, and it can only be the last one, and it means that
the last argument is optional and defaults to $_ if left out.


--
david nicol
Daisy, daisy, give me your answer do
I'm half crazy all for the love of you

David Nicol

unread,
Feb 15, 2004, 6:58:46 PM2/15/04
to Juerd, Perl 5 Porters
On Sun, 2004-02-15 at 17:26, Juerd wrote:

> Why just as the last one? See substr.
>
>

> Juerd

What part of substr deals with the default variable? Substr has

many optional arguments, but there is no AFAICT role of C<$_>
in the calling syntax of substr.

http://www.perldoc.com/perl5.8.0/pod/func/substr.html

does not mention $_. Are you suggesting that substr should,
when called with one argument, treat that argument as the
offset into $_? That might make sense, but it would become
really confusing as you try to add arguments. I;m against it.

Ton Hospel

unread,
Feb 16, 2004, 9:46:32 AM2/16/04
to perl5-...@perl.org
In article <2004021602463...@plover.com>,

Mark Jason Dominus <m...@plover.com> writes:
> On the other hand, if it worked on values and not variables, then
>
> local $/ = "W";
>
> would not affect the value of the magic $/ variable.
>
Ah, but that's an implementation detail. There is actually no reason
(ok, I know. efficiency in having it in a C string internally) that
these magic variables should get their semantics through perl magic.
If input would simply lookup whatever is in the global $/ at that
point, things would work just fine.

The way it works now actually CAUSES bugs, e.g. bug 22613, so
it in fact strengthens my point.

(I wonder if the the current way is really worth it considering I/O
is a relatively slow operation anyways)

And yes, I also realize this wouldn't work for variables like $<.

Ton Hospel

unread,
Feb 16, 2004, 10:04:07 AM2/16/04
to perl5-...@perl.org
In article <c0ql48$rk9$1...@quasar.home.lunix>,

t...@quasar.home.lunix (Ton Hospel) writes:
> And yes, I also realize this wouldn't work for variables like $<.

(sorry for folowing up to myself).

And if magic went with the value (location) instead of the variable
name, local $< would indeed make $< stop working. But that's only
relevant for the magic variables that actually *do* something at
get/set (the others have no reason to use perl magic), and I would in
fact consider losing that magic on localization perfectly reasonable.

Dave Mitchell

unread,
Feb 17, 2004, 9:26:34 AM2/17/04
to david nicol, Perl 5 Porters, ro...@cpan.org
On Sun, Feb 15, 2004 at 06:03:55PM -0600, david nicol wrote:
> On Sun, 2004-02-15 at 17:49, Dave Mitchell wrote:
> > The pad "mapping" is not thrown away, even in the
> > absence of evals.
>
> thanks for correcting me.
>
> Can PadWalker find hidden lexicals?
>
> { my $x; # we're going to hide this
>
> { my $x; # there, first $x is hidden
>
> SomethingThatUsesPadWalker();
> } }
>

Having had a quick peek at the src code for padwalker, No. That's
only because it chooses not to. A similar bit of XS code could find
outer $x's itf it chose to.

PS - Robin, in bleedperl, the SvIVX and SvNVX fields of pad names no
longer contain the seq range if SvFAKE is true, since lexes captured
by a closure are assumed to be in scope for the whole sub; ie the

(valid_at_seq <= SvIVX(name_sv) && valid_at_seq > I_32(SvNVX(name_sv)))

bit needs to become

SvFAKE(sv) || (...)

--
A power surge on the Bridge is rapidly and correctly diagnosed as a faulty
capacitor by the highly-trained and competent engineering staff.
-- Things That Never Happen in "Star Trek" #9

Nick Ing-Simmons

unread,
Feb 19, 2004, 9:22:02 AM2/19/04
to abi...@abigail.nl, Juerd, perl5-...@perl.org

So perhaps we need a prototype that says pass $_ if no args:

sub mychomp (_)
{
}


Nick Ing-Simmons

unread,
Feb 19, 2004, 9:24:20 AM2/19/04
to ju...@convolution.nl, perl5-...@perl.org, Abigail
Juerd <ju...@convolution.nl> writes:
>> But they aren't the same. Witness:
>> $ perl -MO=Deparse -e 'chomp'
>> chomp $_;
>> $
>> 'chomp' doesn't "see" $_. It gets passed on implicitely.
>> How are you going to that for 'bar'?
>
>You can't. It would be great to have a prototype that allows this, but
>that would probably be hard to do, since prototypes don't do that kind
>of thing in Perl 5.

They do exactly that kind of thing - re-interpret the args passed
to the sub.


Nick Ing-Simmons

unread,
Feb 19, 2004, 9:28:47 AM2/19/04
to rgarci...@free.fr, Juerd, perl5-...@perl.org, abi...@abigail.nl
Rafael Garcia-Suarez <rgarci...@free.fr> writes:
>
>> When a sub defaults to $_ and is documented to do that, it is not an
>> accident and the behaviour is wanted.
>
>But there's still a problem.
>
> my_sub($_); # pass $_ by value -- can't modify it
> my_sub(); # if fetches $_, if can modify it.

By perl NEVER passes anything by value, always by refrerence.
Which is why the idiom is

sub foo
{
my ($a,$b,$c) = @_;
but :
$_[0] .= 'x'; # works
}


>
>What you want in fact is a \_ prototype.

No a _ proto will do just fine.

sub warpchomp (_)
{
chomp($_[0]);

Juerd

unread,
Feb 19, 2004, 10:26:58 AM2/19/04
to Nick Ing-Simmons, perl5-...@perl.org
Nick Ing-Simmons skribis 2004-02-19 14:28 (+0000):

> No a _ proto will do just fine.
> sub warpchomp (_)
> {
> chomp($_[0]);
> }

Which would make the lcfirstvowel example something like:

sub lcfirstvowel (;$_) {
my ($foo) = @_;
$foo =~ s/.../.../;
return $foo;
}

If so, I like it :)

Juerd

Juerd

unread,
Feb 19, 2004, 4:55:28 PM2/19/04
to David Nicol, perl5-...@perl.org
David Nicol skribis 2004-02-19 14:56 (-0600):

> >Nick Ing-Simmons skribis 2004-02-19 14:28 (+0000):
> >>No a _ proto will do just fine.
> _ would have to be the last required argument, and would
> generally work like $ except that if it isn't there, $_ gets put in.

That makes sense. Apparently, I wasn't paying attention before.

sub lcfirstvowel (_) { ... }

> All the core functions that accept $_ would suddenly have prototypes
> that can be returned by C<prototype> and emulated.
> prototype "CORE::split"; # this would return $_;$

Nice. This does, however, mean the return value of prototype changes for
most of the builtins. I've never used C<prototype> myself, but maybe
there are scripts/modules floating around that can only deal with the
current C<;$>, but not with the new C<_> that replaces it.

> We could even special-case the simple _ prototype to
> imply running the function on a whole list when a list is
> given in the arguments, like /CORE::chom?p/

Then you lose the distinction between lc-ish and chomp-ish functions and
a nice feature of prototypes (eating only one argument) are lost. What
would you do with the return value?

Besides, it's quite easy to build it yourself with C<for> or C<map>,
when needed.

sub mychomp (_@) { sum map s/\n+\z//, @_ }


Juerd

Rafael Garcia-Suarez

unread,
Feb 19, 2004, 5:42:44 PM2/19/04
to Juerd, David Nicol, perl5-...@perl.org
Juerd wrote:
> sub lcfirstvowel (_) { ... }
>
> > All the core functions that accept $_ would suddenly have prototypes
> > that can be returned by C<prototype> and emulated.
> > prototype "CORE::split"; # this would return $_;$
>
> Nice. This does, however, mean the return value of prototype changes for
> most of the builtins.

Probably feasible. opcode.pl seems to have all the necessary info.

> I've never used C<prototype> myself, but maybe
> there are scripts/modules floating around that can only deal with the
> current C<;$>, but not with the new C<_> that replaces it.

Good remark. I'm not sure we want to change the prototype of built-ins.
There is code out there that overrides built-ins with the proper prototype.

> > We could even special-case the simple _ prototype to
> > imply running the function on a whole list when a list is
> > given in the arguments, like /CORE::chom?p/
>
> Then you lose the distinction between lc-ish and chomp-ish functions and
> a nice feature of prototypes (eating only one argument) are lost. What
> would you do with the return value?
>
> Besides, it's quite easy to build it yourself with C<for> or C<map>,
> when needed.
>
> sub mychomp (_@) { sum map s/\n+\z//, @_ }

Now that's scary.

Juerd

unread,
Feb 19, 2004, 6:43:30 PM2/19/04
to David Nicol, perl5-...@perl.org
David Nicol skribis 2004-02-19 16:25 (-0600):

> >Then you lose the distinction between lc-ish and chomp-ish functions and
> >a nice feature of prototypes (eating only one argument) are lost.
> Why would a function prototyped with one argument eat more than its
> share unless it was forced to? If the idea is to emulate the argument
> dining habits of C<chop>, that function currently politely eats a
> single arg unless you insist:

I stand corrected.

Still, it would introduce some unfortunate differences between builtins
that take $_ implicitly and your own functions that do so: context is no
longer forced (length @foo).

> We'd ape what chop does.

chop mutates its arguments and returns the last character removed;
chomp mutates its arguments and returns the total number of characters removed;
reverse returns its arguments in reversed order;
unlink returns the number of succesful unlinks.

There is no consistency.

Why do what chop does and not what chomp does? Of these four, I think
it's the most useless one. I suspect nobody uses the return value of
chop called with more than one argument, but that people would use it if
it was a number of characters removed or a list of characters removed.


I do not think implicit looping is a good idea.


Juerd

Juerd

unread,
Feb 19, 2004, 6:48:23 PM2/19/04
to Rafael Garcia-Suarez, perl5-...@perl.org
Rafael Garcia-Suarez skribis 2004-02-19 23:42 (+0100):

> > I've never used C<prototype> myself, but maybe
> > there are scripts/modules floating around that can only deal with the
> > current C<;$>, but not with the new C<_> that replaces it.
> Good remark. I'm not sure we want to change the prototype of built-ins.
> There is code out there that overrides built-ins with the proper prototype.

I think David is right and that the current behavior should indeed be
considered a bug.

The prototype of lc is not ";$", but it takes the introduction of a
lexical $_ for anyone to notice the real difference :)

> > sub mychomp (_@) { sum map s/\n+\z//, @_ }
> Now that's scary.

Why? Only the _ in the prototype is different from what is already
possible. One would in current Perl write:

sub mychomp (@) { @_ or @_ = $_; sum map ... }

(Except probably without the prototype)


Juerd

Juerd

unread,
Feb 19, 2004, 7:01:35 PM2/19/04
to Chip Salzenberg, perl5-...@perl.org
Chip Salzenberg skribis 2004-02-19 18:13 (-0500):
> According to Juerd:

> > sub mychomp (_@) { sum map s/\n+\z//, @_ }
> Don't you mean:
> sub mychomp (_@) { grep s/(?:$/)+\z//, @_ }

$/ => yes [though it's *my*chomp, so it can do whatever I want :)].

grep => no.

s/// with $/ in it => no, the slash ends the pattern :)


Summing the return values of the substitution is a bit chomp-ish. chomp
returns the number of characters that it removed, mychomp would return
the number of elements it mutated.

To make it more like the real chomp:

sub mychomp (_@) { sum map s[((?:$/)+)\z][] && length $1, @_ }


Juerd

Chip Salzenberg

unread,
Feb 19, 2004, 7:54:18 PM2/19/04
to Juerd, perl5-...@perl.org
According to Juerd:

> Chip Salzenberg skribis 2004-02-19 18:13 (-0500):
> > According to Juerd:
> > > sub mychomp (_@) { sum map s/\n+\z//, @_ }
> > Don't you mean:
> > sub mychomp (_@) { grep s/(?:$/)+\z//, @_ }
>
> grep => no.

I suppose I should have said "scalar grep", since the scalar version
is what I wanted, which returns the count of boolean true evaluations.

> s/// with $/ in it => no, the slash ends the pattern :)

D'oh.
--
Chip Salzenberg - a.k.a. - <ch...@pobox.com>
"I wanted to play hopscotch with the impenetrable mystery of existence,
but he stepped in a wormhole and had to go in early." // MST3K

0 new messages