lexical subs

3 views
Skip to first unread message

H.Merijn Brand

unread,
Mar 9, 2007, 2:45:15 AM3/9/07
to Perl5 Porters
Now that we have lexical $_, why not lexical subs

if ($some_expression) {
sub complex_calc {
# Some very complex calculus for this lexical scope only
}
my $foo = complex_calc (.....) + complex_calc (.....);
my $bar = $foo * complex_calc (.....);
# etc
}
if ($some_similar_expr) {
sub complex_calc {
# Some very complex calculus for this lexical scope only
}
my $foo = complex_calc (.....) + complex_calc (.....);
my $bar = $foo * complex_calc (.....);
# etc
}

And guess what happens without a warning
Same if complex_calc would also have been defined outside of
the scope(s). It would be so handy and useful to be able to

if (...) {
my sub handy {
# ...
}
# ...
}
if (...) {
my sub handy {
# ...
}
# ...
}

and now have *two* functions handy () that are invisible
outside of the lexical scope.

This would also be an ideal solution to hide private
functions and methods inside modules.

feasible? useful? doable?

--
H.Merijn Brand Amsterdam Perl Mongers (http://amsterdam.pm.org/)
using & porting perl 5.6.2, 5.8.x, 5.9.x on HP-UX 10.20, 11.00, 11.11,
& 11.23, SuSE 10.0 & 10.2, AIX 4.3 & 5.2, and Cygwin. http://qa.perl.org
http://mirrors.develooper.com/hpux/ http://www.test-smoke.org
http://www.goldmark.org/jeff/stupid-disclaimers/

Dr.Ruud

unread,
Mar 9, 2007, 4:10:54 AM3/9/07
to perl5-...@perl.org
"H.Merijn Brand" schreef:

> Now that we have lexical $_, why not lexical subs
>
> if ($some_expression) {
> sub complex_calc {
> # Some very complex calculus for this lexical scope only
> }
> my $foo = complex_calc (.....) + complex_calc (.....);
> my $bar = $foo * complex_calc (.....);
> # etc
> }
> if ($some_similar_expr) {
> sub complex_calc {
> # Some very complex calculus for this lexical scope only
> }
> my $foo = complex_calc (.....) + complex_calc (.....);
> my $bar = $foo * complex_calc (.....);
> # etc
> }

There already is $complex_calc->(), which can be used well for above
example. But that just makes the example bad; lexical subs would be
great to have.

--
Affijn, Ruud

"Gewoon is een tijger."

H.Merijn Brand

unread,
Mar 9, 2007, 4:39:41 AM3/9/07
to perl5-...@perl.org
On Fri, 9 Mar 2007 10:10:54 +0100, "Dr.Ruud" <rvtol...@isolution.nl> wrote:

> "H.Merijn Brand" schreef:
>
> > Now that we have lexical $_, why not lexical subs
> >
> > if ($some_expression) {
> > sub complex_calc {
> > # Some very complex calculus for this lexical scope only
> > }
> > my $foo = complex_calc (.....) + complex_calc (.....);
> > my $bar = $foo * complex_calc (.....);
> > # etc
> > }
> > if ($some_similar_expr) {
> > sub complex_calc {
> > # Some very complex calculus for this lexical scope only
> > }
> > my $foo = complex_calc (.....) + complex_calc (.....);
> > my $bar = $foo * complex_calc (.....);
> > # etc
> > }
>
> There already is $complex_calc->(), which can be used well for above

Which is what I used

> example. But that just makes the example bad; lexical subs would be
> great to have.

Rafael said that the parser already knows how to do it, but added:
"but nobody figured out what to make with that" :)
Now I hope my example just makes enough sense to someone to just
make it happen.

Tels

unread,
Mar 9, 2007, 5:47:28 AM3/9/07
to perl5-...@perl.org, H.Merijn Brand
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Moin,

On Friday 09 March 2007 07:45:15 H.Merijn Brand wrote:
> Now that we have lexical $_, why not lexical subs
>
> if ($some_expression) {
> sub complex_calc {
> # Some very complex calculus for this lexical scope only
> }
> my $foo = complex_calc (.....) + complex_calc (.....);
> my $bar = $foo * complex_calc (.....);
> # etc
> }
> if ($some_similar_expr) {
> sub complex_calc {
> # Some very complex calculus for this lexical scope only
> }
> my $foo = complex_calc (.....) + complex_calc (.....);
> my $bar = $foo * complex_calc (.....);
> # etc
> }
>
> And guess what happens without a warning
> Same if complex_calc would also have been defined outside of
> the scope(s). It would be so handy and useful to be able to

I really don't like the idea of having two subroutines with the same name,
this makes code only more confusing.

You can always do the equivalent of:

$complex_calc = sub { ... };

$foo = $complex_calc->(123) + $complex_calc->(124);

so would this scheme only save you writing the "$" and the "->"?

All the best,

Tels

- --
Signed on Fri Mar 9 10:10:11 2007 with key 0x93B84C15.
View my photo gallery: http://bloodgate.com/photos
PGP key on http://bloodgate.com/tels.asc or per email.

"Don't worry about people stealing your ideas. If your ideas are any
good, you'll have to ram them down people's throats."

-- Howard Aiken
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iQEVAwUBRfE7QHcLPEOTuEwVAQJb5wf5AQ2juENVmfqORKPePmm2QPeuk0BWadun
WWNHCjpuLznb2bZB0BcoAYheLM5vya6O2BclC7K21mVdO0phG9zRUsqR0bDjFdcM
njxb+fih0Af7e1c1L8aY0dLJglMYB3IOa6fjQn2nbHyoqGwdUTRCh3dzyWzvs4OW
XOIekrRAXkBjmTDN0hqX9SjtxS2Hdy8WupS+pwNU+pajB6ffmTfJPhL7V+UlQIJa
3tJTR8+XwZO6Tk47TofeYM/oP7G2WWJp4zHNUkTtJcqk7M10YvgmWo+Ny44FCV3R
RA36FlXcK3TOp4ua+D69Izplv6bkIfXKqiCFQ/uyENelExuWYt7p/w==
=6Rdx
-----END PGP SIGNATURE-----

Johan Vromans

unread,
Mar 9, 2007, 5:03:54 AM3/9/07
to Tels, perl5-...@perl.org, H.Merijn Brand
Tels <nospam...@bloodgate.com> writes:

> I really don't like the idea of having two subroutines with the same
> name, this makes code only more confusing.

... unless they're lexical.

I assume you're not bothered by multiple occurrances of a lexical $i
or so?

-- Johan

H.Merijn Brand

unread,
Mar 9, 2007, 5:02:46 AM3/9/07
to perl5-...@perl.org
On Fri, 9 Mar 2007 10:47:28 +0000, Tels <nospam...@bloodgate.com> wrote:
> On Friday 09 March 2007 07:45:15 H.Merijn Brand wrote:
> > Now that we have lexical $_, why not lexical subs
> >
> > if ($some_expression) {
> > sub complex_calc {
> > # Some very complex calculus for this lexical scope only
> > }
> > my $foo = complex_calc (.....) + complex_calc (.....);
> > my $bar = $foo * complex_calc (.....);
> > # etc
> > }
> > if ($some_similar_expr) {
> > sub complex_calc {
> > # Some very complex calculus for this lexical scope only
> > }
> > my $foo = complex_calc (.....) + complex_calc (.....);
> > my $bar = $foo * complex_calc (.....);
> > # etc
> > }
> >
> > And guess what happens without a warning
> > Same if complex_calc would also have been defined outside of
> > the scope(s). It would be so handy and useful to be able to
>
> I really don't like the idea of having two subroutines with the
> same name, this makes code only more confusing.

You're free to use it, or not. Just like with most features

> You can always do the equivalent of:
>
> $complex_calc = sub { ... };
>
> $foo = $complex_calc->(123) + $complex_calc->(124);

Of course, and - as said, that is what I had to use right now,
but not only is it ugly (it looks like OO where it isn't), but
also stupid if you think about what you wanted.

> so would this scheme only save you writing the "$" and the "->"?

Though the gain in less keystrokes is a plus, this is not the
motivation to ask for it.

Abigail

unread,
Mar 9, 2007, 5:22:21 AM3/9/07
to Tels, perl5-...@perl.org, H.Merijn Brand
On Fri, Mar 09, 2007 at 10:47:28AM +0000, Tels wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Moin,
>
> On Friday 09 March 2007 07:45:15 H.Merijn Brand wrote:
> > Now that we have lexical $_, why not lexical subs
> >
> > if ($some_expression) {
> > sub complex_calc {
> > # Some very complex calculus for this lexical scope only
> > }
> > my $foo = complex_calc (.....) + complex_calc (.....);
> > my $bar = $foo * complex_calc (.....);
> > # etc
> > }
> > if ($some_similar_expr) {
> > sub complex_calc {
> > # Some very complex calculus for this lexical scope only
> > }
> > my $foo = complex_calc (.....) + complex_calc (.....);
> > my $bar = $foo * complex_calc (.....);
> > # etc
> > }
> >
> > And guess what happens without a warning
> > Same if complex_calc would also have been defined outside of
> > the scope(s). It would be so handy and useful to be able to
>
> I really don't like the idea of having two subroutines with the same name,
> this makes code only more confusing.

How's that different from having two variables with the same name?

> You can always do the equivalent of:
>
> $complex_calc = sub { ... };
>
> $foo = $complex_calc->(123) + $complex_calc->(124);
>
> so would this scheme only save you writing the "$" and the "->"?

Yes, and? If that would be the enough reason not to add something to
Perl, Perl wouldn't be as rich as it is.

Abigail

Tels

unread,
Mar 9, 2007, 6:25:34 AM3/9/07
to perl5-...@perl.org, Johan Vromans, H.Merijn Brand
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Moin,

On Friday 09 March 2007 10:03:54 Johan Vromans wrote:
> Tels <nospam...@bloodgate.com> writes:
> > I really don't like the idea of having two subroutines with the same
> > name, this makes code only more confusing.
>
> ... unless they're lexical.

? if you have lexical and global subroutines, then the line:

$foo = complex_calc() + complex_calc();

cannot examined without checking the lexical scope to see what sort of
complex_calc() is actually called. Computers are very good at this, but
humans are not.

(I disregard the (ab)use of toying around with *complex_calc here for a
moment)

> I assume you're not bothered by multiple occurrances of a lexical $i
> or so?

Usually, $i is lexical. Globals are rare, and generally regarded as bad.

So in:

$foo = complex_calc() + complex_calc();

is very likely that $foo is a lexical. (Yes, I wish you wouldn't have people
adding global $foos - but that is another matter :)

At least now you know that a variable can be lexical or global (although
globals are usually regared as a bad idea), but subroutines are
always "global" so to speak.

So in praxis you end up with a lot of lexical variables, and some globals
(or lots, in bad code) and file-scoped sub routines.

If you can have lexical subroutines, well, it's one more way to write the
same code, slightly different. I am not sure it is really nec. to invent
YetAnotherWayToDoIt.

As for the "you dont have to use it" - no, but I will eventually have to
maintain code that (ab)uses it. :-)

So far, this new feature looks like a solution in search of a problem.

Of course, that never has stopped anyone :) So Don't let my opinion get in
the way of adding Cool New Features[tm] :-)

All the best,

Tels

- --
Signed on Fri Mar 9 11:16:52 2007 with key 0x93B84C15.


View my photo gallery: http://bloodgate.com/photos
PGP key on http://bloodgate.com/tels.asc or per email.

"A bus station is where a bus stops. A train station is where a train
stops. On my desk I have a work station."

-- Unknown


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iQEVAwUBRfFELncLPEOTuEwVAQLdSAf9Ha17BwX9oCTq0NOA8gmHnWsPUjgxn9aZ
y0zUwAVQ416I2mkyN7KmESSX4FXJMcgn0Q8d2LG7w4aXKf03nljnr16qHR4yFQ0o
b9yeLZrl26SsWXWYVhMAhOm1h8mog42wtqftNS4iuK3GuJfldJoE9AL+gMMqO3KT
0orR16wtPKdFkEI22uXf3RRA3jVwzIbsBxY6XLmSLbdZ/3V2fQDDg7q76GlQTUAa
2L5zRtJ426AiZhNDKy7xUGkl/ZPVD8oauMPRM450MXYfkUdDq8HvLXLx4tA6nJTu
uxsrp76Lwoc+jqEZvDSkQOsL2BHz4G+W/kMXnEYhdornJNi5aLQemQ==
=9hfG
-----END PGP SIGNATURE-----

Demerphq

unread,
Mar 9, 2007, 5:39:30 AM3/9/07
to Tels, H.Merijn Brand, perl5-...@perl.org
On 3/9/07, Tels <nospam...@bloodgate.com> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Moin,
>
> On Friday 09 March 2007 07:45:15 H.Merijn Brand wrote:
> > Now that we have lexical $_, why not lexical subs
> >
> > if ($some_expression) {
> > sub complex_calc {
> > # Some very complex calculus for this lexical scope only
> > }
> > my $foo = complex_calc (.....) + complex_calc (.....);
> > my $bar = $foo * complex_calc (.....);
> > # etc
> > }
> > if ($some_similar_expr) {
> > sub complex_calc {
> > # Some very complex calculus for this lexical scope only
> > }
> > my $foo = complex_calc (.....) + complex_calc (.....);
> > my $bar = $foo * complex_calc (.....);
> > # etc
> > }
> >
> > And guess what happens without a warning
> > Same if complex_calc would also have been defined outside of
> > the scope(s). It would be so handy and useful to be able to

Unless you can differentiate between a sub declared in a bare block
and a sub declared in a condition I think this is a non starter as it
would break anything that used a block to make a named subroutine into
a closure so as to simulate a static var.

{
my $counter;
sub next_id { return ++$counter }
}


> I really don't like the idea of having two subroutines with the same name,
> this makes code only more confusing.
>
> You can always do the equivalent of:
>
> $complex_calc = sub { ... };
>
> $foo = $complex_calc->(123) + $complex_calc->(124);
>
> so would this scheme only save you writing the "$" and the "->"?

If i understand it correctly this isnt quite right. When you want to
do a recursive subroutine with lexically scoped references to
anonymous subroutines you have to be extremely careful not to end up
with a memory leak. Using named subroutines doesn't have this problem,
so from that point of view IMO this would be an improvement.

Cheers,
yves

--
perl -Mre=debug -e "/just|another|perl|hacker/"

Tels

unread,
Mar 9, 2007, 6:34:05 AM3/9/07
to perl5-...@perl.org, Abigail, H.Merijn Brand
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Moin,

On Friday 09 March 2007 10:22:21 Abigail wrote:
> On Fri, Mar 09, 2007 at 10:47:28AM +0000, Tels wrote:
> > -----BEGIN PGP SIGNED MESSAGE-----
> > Hash: SHA1
> >
> > Moin,

[snip]


> > I really don't like the idea of having two subroutines with the same
> > name, this makes code only more confusing.
>
> How's that different from having two variables with the same name?

At least with a naked call to a subroutine, you know now it is the *one*.

$deity knows there is already twisted enough Perl code out there that we
really don't need to add more complexity. IMHO of course.

> > You can always do the equivalent of:
> >
> > $complex_calc = sub { ... };
> >
> > $foo = $complex_calc->(123) + $complex_calc->(124);
> >
> > so would this scheme only save you writing the "$" and the "->"?
>
> Yes, and? If that would be the enough reason not to add something to
> Perl, Perl wouldn't be as rich as it is.

If you have to maintain code, million little ways to write the same code are
actually not a good idea.

Global variables, (ab)usive use of $_, side effects, actions-at-a distance,
very short variable names for long stretches of code, this are all things
that make it much harder to understand the code for humans.

And I don't think piling on yet-another-way to acomplish the same is a good
idea, especially if it doesn't actually look to savemore than a few
keystrokes, but creates confusion on the wake.

However, don't let me discourage you. At least the golfers will love
it... :)

All the best,

Tels

- --
Signed on Fri Mar 9 11:25:55 2007 with key 0x93B84C15.
Get one of my photo posters: http://bloodgate.com/posters


PGP key on http://bloodgate.com/tels.asc or per email.

"...pornographic images stay in the brain forever." - Mary Anne Layden

"That's a feature, not a bug." - God

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iQEVAwUBRfFGLXcLPEOTuEwVAQLhCAf+OttQX5JVdYQim7qvWeuwoOpE1l/1OLfx
2d0r34JgUadVQKWuX1ZfwU/lMtmMhtyd2LOWOmtnWNRNJBmasm7Q62TCVF841wnN
2r+3oNbn+BneIH0HAOqlXaZ0NN9THQTxB47T1e3t7l2C/IjKeS/qTmljrPBFnP6j
pMgtkHpoBcWY0+mZHd2VLv/MYpMIlfuAyvUBKG/o/xPh3u7exgfH0IRCpjyivA0N
oa2i9sHmaCaCDptpkuFvyWdXazs5s2W7+ioBLqtFruKLwWJ1RxH9MXtSJB2bnqn6
e+ctGXZ7LdrXrx7dgOE02OC1Qdm4tjeo+qtd1CWes5u06sZDkdth5A==
=j8aI
-----END PGP SIGNATURE-----

Abigail

unread,
Mar 9, 2007, 5:41:08 AM3/9/07
to Tels, perl5-...@perl.org, Johan Vromans, H.Merijn Brand
On Fri, Mar 09, 2007 at 11:25:34AM +0000, Tels wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Moin,
>
> On Friday 09 March 2007 10:03:54 Johan Vromans wrote:
> > Tels <nospam...@bloodgate.com> writes:
> > > I really don't like the idea of having two subroutines with the same
> > > name, this makes code only more confusing.
> >
> > ... unless they're lexical.
>
> ? if you have lexical and global subroutines, then the line:
>
> $foo = complex_calc() + complex_calc();
>
> cannot examined without checking the lexical scope to see what sort of
> complex_calc() is actually called. Computers are very good at this, but
> humans are not.

And that is worse than checking the entire %INC tree for complex_calc()?

>
> (I disregard the (ab)use of toying around with *complex_calc here for a
> moment)
>
> > I assume you're not bothered by multiple occurrances of a lexical $i
> > or so?
>
> Usually, $i is lexical. Globals are rare, and generally regarded as bad.

Yes, and? I fail to see why that fact that a sub can be lexical is
confusing, while at the mean time, it's not confusing for variables.

Noone really cares whether a particular variable is lexical or global.
What matters is if I have a variable $foo and it's used in lines X and Y,
whether that's the same $foo or not. Even it's given that $foo is lexical
doesn't answer the question. Yet programmers aren't confused by that, in
fact, it's consider a *good* thing to have lexical variables.

Since it isn't confusing for variables, why would it be for subs?

Abigail

Abigail

unread,
Mar 9, 2007, 5:55:51 AM3/9/07
to Rafael Garcia-Suarez, H.Merijn Brand, Perl5 Porters
On Fri, Mar 09, 2007 at 11:46:25AM +0100, Rafael Garcia-Suarez wrote:
> On 09/03/07, H.Merijn Brand <h.m....@xs4all.nl> wrote:
> >Now that we have lexical $_, why not lexical subs
>
> From what I see in Synopsis 6, Perl 6 has lexical subs.
> The perl 5 parser has them, too :
>
> $ bleadperl -e 'my sub foo'
> "my sub" not yet implemented at -e line 1.
>
> What's missing is actually implementing them, that is, storing them in
> the pad and looking them up there. (And adding warnings when a lexical
> hides a global, etc)
> Also, if we want "my sub", we probably want "our sub" too.
> But I see no pressing need for that. Especially because I consider
> 5.10 to be almost finished :)


$ echo "lexical subs" >> perl5.14todo


;-)

Abigail

Demerphq

unread,
Mar 9, 2007, 5:53:25 AM3/9/07
to Rafael Garcia-Suarez, H.Merijn Brand, Perl5 Porters
On 3/9/07, Rafael Garcia-Suarez <rgarci...@gmail.com> wrote:
> On 09/03/07, H.Merijn Brand <h.m....@xs4all.nl> wrote:
> > Now that we have lexical $_, why not lexical subs
>
> From what I see in Synopsis 6, Perl 6 has lexical subs.
> The perl 5 parser has them, too :
>
> $ bleadperl -e 'my sub foo'
> "my sub" not yet implemented at -e line 1.
>
> What's missing is actually implementing them, that is, storing them in
> the pad and looking them up there. (And adding warnings when a lexical
> hides a global, etc)
> Also, if we want "my sub", we probably want "our sub" too.
> But I see no pressing need for that. Especially because I consider
> 5.10 to be almost finished :)

I dont think we do need an our sub. our isnt a declaration like my is,
its just a pragma for strict.

my sub foo { ... };

is apparently the same thing as

local *foo=sub { ... };

I think it might be a nice as a syntax enhancement, but i think its
potentially confusing, as it crosses the divide between dynamic and
lexical values. Maybe this could be resolved by making the syntax:

local sub foo { ... };

so the meaning is clear. Anyway, if this meme becomes common then we
will need to look into changine the method-cache as it will be spoiled
every time this code is executed.

cheers,

Rafael Garcia-Suarez

unread,
Mar 9, 2007, 5:46:25 AM3/9/07
to H.Merijn Brand, Perl5 Porters
On 09/03/07, H.Merijn Brand <h.m....@xs4all.nl> wrote:
> Now that we have lexical $_, why not lexical subs

From what I see in Synopsis 6, Perl 6 has lexical subs.

Abigail

unread,
Mar 9, 2007, 5:52:41 AM3/9/07
to Tels, perl5-...@perl.org, H.Merijn Brand
On Fri, Mar 09, 2007 at 11:34:05AM +0000, Tels wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Moin,
>
> On Friday 09 March 2007 10:22:21 Abigail wrote:
> > On Fri, Mar 09, 2007 at 10:47:28AM +0000, Tels wrote:
> > > -----BEGIN PGP SIGNED MESSAGE-----
> > > Hash: SHA1
> > >
> > > Moin,
> [snip]
> > > I really don't like the idea of having two subroutines with the same
> > > name, this makes code only more confusing.
> >
> > How's that different from having two variables with the same name?
>
> At least with a naked call to a subroutine, you know now it is the *one*.

At least with lexical subroutines, its definition is 'close', and not
somewhere burried in a twingled maze of "use"d modules.

> $deity knows there is already twisted enough Perl code out there that we
> really don't need to add more complexity. IMHO of course.
>
> > > You can always do the equivalent of:
> > >
> > > $complex_calc = sub { ... };
> > >
> > > $foo = $complex_calc->(123) + $complex_calc->(124);
> > >
> > > so would this scheme only save you writing the "$" and the "->"?
> >
> > Yes, and? If that would be the enough reason not to add something to
> > Perl, Perl wouldn't be as rich as it is.
>
> If you have to maintain code, million little ways to write the same code are
> actually not a good idea.

No, but Perl doesn't have a history of having that as one of its main
points. OTOH, having more than one way of doing things is considered
to be a Perlish thing.

> Global variables, (ab)usive use of $_, side effects, actions-at-a distance,
> very short variable names for long stretches of code, this are all things
> that make it much harder to understand the code for humans.

Ah, yes. If only Perl was designed to not have global variables, $_,
side-effects, short variables, then we wouldn't have any of the problems
you just mention. We wouldn't have the language we have now though.

Now, there could be all kinds of reasons not to add lexical subroutines
(or any other feature) to Perl, but "it can be used in such a way that
code becomes harder to understand", is IMO, a bad reason to dismiss a
feature.

> And I don't think piling on yet-another-way to acomplish the same is a good
> idea, especially if it doesn't actually look to savemore than a few
> keystrokes, but creates confusion on the wake.
>
> However, don't let me discourage you. At least the golfers will love
> it... :)


Real golfers don't use subroutines.

Abigail

H.Merijn Brand

unread,
Mar 9, 2007, 5:48:40 AM3/9/07
to perl5-...@perl.org

No, as there is no "my" there. It would be different with

{ my $counter;
my sub next_id { return ++$counter }
}

but that is kinda useless anyway

> > I really don't like the idea of having two subroutines with the same name,
> > this makes code only more confusing.
> >
> > You can always do the equivalent of:
> >
> > $complex_calc = sub { ... };
> >
> > $foo = $complex_calc->(123) + $complex_calc->(124);
> >
> > so would this scheme only save you writing the "$" and the "->"?
>
> If i understand it correctly this isnt quite right. When you want to
> do a recursive subroutine with lexically scoped references to
> anonymous subroutines you have to be extremely careful not to end up
> with a memory leak. Using named subroutines doesn't have this problem,
> so from that point of view IMO this would be an improvement.

--

Demerphq

unread,
Mar 9, 2007, 6:11:27 AM3/9/07
to Rafael Garcia-Suarez, H.Merijn Brand, Perl5 Porters
On 3/9/07, Rafael Garcia-Suarez <rgarci...@gmail.com> wrote:
> On 09/03/07, demerphq <deme...@gmail.com> wrote:
> > I dont think we do need an our sub. our isnt a declaration like my is,
> > its just a pragma for strict.
>
> That was just for symmetry. (I don't want to think about "state sub foo{}".)

>
> > my sub foo { ... };
> >
> > is apparently the same thing as
> >
> > local *foo=sub { ... };
>
> (You meant local &foo, if perl supported that syntax)

Well to be totally picky i think i meant:

local *foo=*foo;
*foo=sub { ... };

> I don't think so. my only restricts visibility at compilation time,
> while local has a runtime effect.

Ok,clearly i was having a mental block on this stuff. I get it now.

Cheers,
Yves

Rafael Garcia-Suarez

unread,
Mar 9, 2007, 6:00:34 AM3/9/07
to demerphq, H.Merijn Brand, Perl5 Porters
On 09/03/07, demerphq <deme...@gmail.com> wrote:
> I dont think we do need an our sub. our isnt a declaration like my is,
> its just a pragma for strict.

That was just for symmetry. (I don't want to think about "state sub foo{}".)

> my sub foo { ... };


>
> is apparently the same thing as
>
> local *foo=sub { ... };

(You meant local &foo, if perl supported that syntax)

Aaron Crane

unread,
Mar 9, 2007, 6:39:02 AM3/9/07
to perl5-...@perl.org
Tels writes:
> You can always do the equivalent of:
>
> $complex_calc = sub { ... };
> $foo = $complex_calc->(123) + $complex_calc->(124);
>
> so would this scheme only save you writing the "$" and the "->"?

You'd also get the benefit that a sub with a fully-lexical name
couldn't be mistaken for a method by something attempting to
perform introspection on your class.

--
Aaron Crane

Wolfgang Laun

unread,
Mar 9, 2007, 8:21:58 AM3/9/07
to h.m....@xs4all.nl, perl5-...@perl.org
On Fri, 9 Mar 2007 11:48:40 +0100 H.Merijn Brand wrote:

> No, as there is no "my" there. It would be different with
>

> my sub next_id { return ++$counter }
>

If this is meant to restrict visibility to the scope
where it is written, also outside any {...}:
Will we see information hiding in Perl yet? ;-)

sub new { ... }
my sub localMethod {...}
sub publicMethod { shift->localMethod(); }

This, too?

kr
Wolfgang


Rafael Garcia-Suarez

unread,
Mar 9, 2007, 9:16:44 AM3/9/07
to Wolfgang Laun, h.m....@xs4all.nl, perl5-...@perl.org
On 09/03/07, Wolfgang Laun <Wolfga...@thalesgroup.com> wrote:
> sub new { ... }
> my sub localMethod {...}
> sub publicMethod { shift->localMethod(); }
>
> This, too?

That's a whole can of worms. See, what to do with $obj->$method()
where $method="localMethod" ? What to do with $obj->can("localMethod")
? Will we forced to blow up the method cache every time the scope is
entered or exited ? etc etc.

Paul Johnson

unread,
Mar 9, 2007, 9:32:47 AM3/9/07
to Abigail, Tels, perl5-...@perl.org, H.Merijn Brand
On Fri, Mar 09, 2007 at 11:52:41AM +0100, Abigail wrote:
> On Fri, Mar 09, 2007 at 11:34:05AM +0000, Tels wrote:
> > On Friday 09 March 2007 10:22:21 Abigail wrote:
> > > On Fri, Mar 09, 2007 at 10:47:28AM +0000, Tels wrote:
> > > > I really don't like the idea of having two subroutines with the same
> > > > name, this makes code only more confusing.
> > >
> > > How's that different from having two variables with the same name?
> >
> > At least with a naked call to a subroutine, you know now it is the *one*.
>
> At least with lexical subroutines, its definition is 'close', and not
> somewhere burried in a twingled maze of "use"d modules.

IMHO, lexical subroutines are to global subroutines as lexical variables are
to global variables. If you have used a language that allows them, you may
well miss them in Perl. If not, you probably don't know what you are missing.

I would be very happy to see them in Perl, but I would prefer to see 5.10 out
first.

--
Paul Johnson - pa...@pjcj.net
http://www.pjcj.net

Jan Dubois

unread,
Mar 9, 2007, 10:34:57 AM3/9/07
to Abigail, Rafael Garcia-Suarez, H.Merijn Brand, Perl5 Porters
On Fri, 09 Mar 2007, Abigail wrote:
>
> $ echo "lexical subs" >> perl5.14todo

I was about to say "it's already in there", but when I checked
it was gone. In Perl 5.6.1 perltodo.pod contains:

| =item Scoped subs
|
| lexically-scoped subs, e.g. my sub

I guess this has been removed somewhat prematurely when the
syntax was added to the parser.

Cheers,
-Jan

Mark Jason Dominus

unread,
Mar 9, 2007, 2:13:41 PM3/9/07
to Perl5 Porters

I don't care much whether this goes in or not, but if someone does
come up with an implementation, I humbly request that they notify me
before releasing it, since I can supply a whole bookful of test cases
for this feature. Some of these test cases will exercise behaviors
that the implementor may not have considered.

For example, what does this do?

sub fib { die; }

{
my sub fib {
my $n = shift;
return $n < 2 ? $n : fib($n-1) + fib($n-2);
};
}

David Nicol

unread,
Mar 9, 2007, 3:02:32 PM3/9/07
to Mark Jason Dominus, Perl5 Porters
On 3/9/07, Mark Jason Dominus <m...@plover.com> wrote:

> For example, what does this do?
>
> sub fib { die; }
>
> {
> my sub fib {
> my $n = shift;
> return $n < 2 ? $n : fib($n-1) + fib($n-2);
> };
> }

absolutely nothing, since there is no way to call the inner one :)
The discussion
below assumes that the ellipsis after the lexical sub def was left
out by mistake.

Following the model of my $var = EXPR, where $var is not visible within EXPR,
that would die on any $n GE 2. To get a recursive lexical sub you'd have
to declare the sub (and its prototype) within the scope before defining it:
{
- my sub fib {
+ my sub fib;
+ sub fib {


my $n = shift;
return $n < 2 ? $n : fib($n-1) + fib($n-2);
};

+ ... # stuff that can see my sub fib
}


Without further exercise of restraint, here's my opinion of the
feature in question:
We don't need it as it would further confuse things. The test for
inclusion seems
to be if the proponent of the feature feels strongly enough about the
need for it
to make it work and there aren't serious objections, in it goes. I
think that the
current ability to assign a coderef to a scalar is sufficient for all
possible use
cases, and the additional decoration on the resulting calls is a good thing as
it makes lexically scoped routines look different. And $name->(ARGLIST)
does not look like a method call to my eyes. A method call looks like
$name->method(ARGLIST) -- notice the token between the arrow and the (.

bash-3.00# perl -l
{ my $subfib;
$subfib = sub {
my $n = shift;
return $n < 2 ? $n : $subfib->($n-1) + $subfib->($n-2);
};
print $subfib->($_) for 1..10;
}

__END__
1
1
2
3
5
8
13
21
34
55
bash-3.00#

--
"Big discoveries are protected by public incredulity." -- Marshall McLuhan

Jan Dubois

unread,
Mar 9, 2007, 3:19:51 PM3/9/07
to Michael G Schwern, Mark Jason Dominus, Perl5 Porters
On Fri, 09 Mar 2007, Michael G Schwern wrote:
> This will recurse into the lexical fib() routine.

>
> sub fib { die }
>
> {
> my sub fib {
> my $n = shift;
> return $n < 2 ? $n : fib($n-1) + fib($n-2);
> };
>
> fib(5);
> }

Nope, this should die too (in the first recursive call). Any calls to
fib() from inside the lexical function will not result in recursion but
call the function visible in the outer scope. This has to be consistent
with usage like this:

$x = 10;
{
my $x = $x + 1;
print $x;
}

This has to print 11 and not 1 because the right hand side of the
assignment to the lexical still references the variable from the
outer scope.

This make the lexical sub form unsuitable for recursive function.

You could work around it by allowing:

my sub fib;
my sub fib { ... fib() } ;

This is still inconsistent with the way multiple "my" declarations
work for other variables.

Cheers,
-Jan


Michael G Schwern

unread,
Mar 9, 2007, 3:01:00 PM3/9/07
to Mark Jason Dominus, Perl5 Porters

Well, nothing since you only declared functions and didn't call then. :)
Anyhow, good question.

The following will die.

sub fib { die }

{
my sub fib {
my $n = shift;
return $n < 2 ? $n : fib($n-1) + fib($n-2);
};
}

fib(5);


This will recurse into the lexical fib() routine.

sub fib { die }

{
my sub fib {
my $n = shift;
return $n < 2 ? $n : fib($n-1) + fib($n-2);
};

fib(5);
}


And this will die.

sub fib { die }

{
fib(5);

Juerd Waalboer

unread,
Mar 9, 2007, 3:32:20 PM3/9/07
to perl6-l...@perl.org, perl5-...@perl.org
Juerd Waalboer skribis 2007-03-09 21:27 (+0100):
> Just a short note: please, if this is implemented, make sure that either
> Perl 6 conforms to Perl 5 behaviour, or the other way around.

Wanted to CC this list, but by accident replaced the To instead. Now
CC'ing p5p.
--
korajn salutojn,

juerd waalboer: perl hacker <ju...@juerd.nl> <http://juerd.nl/sig>
convolution: ict solutions and consultancy <sa...@convolution.nl>

Ik vertrouw stemcomputers niet.
Zie <http://www.wijvertrouwenstemcomputersniet.nl/>.

Michael G Schwern

unread,
Mar 9, 2007, 3:23:09 PM3/9/07
to David Nicol, Mark Jason Dominus, Perl5 Porters
David Nicol wrote:
> On 3/9/07, Mark Jason Dominus <m...@plover.com> wrote:
>
>> For example, what does this do?
>>
>> sub fib { die; }
>>
>> {
>> my sub fib {
>> my $n = shift;
>> return $n < 2 ? $n : fib($n-1) + fib($n-2);
>> };
>> }
>
> absolutely nothing, since there is no way to call the inner one :)

Zounds! I fell into his infernal trap!

Of course, "my $code = sub" acts exactly the same way.


> Without further exercise of restraint, here's my opinion of the
> feature in question:
> We don't need it as it would further confuse things. The test for
> inclusion seems
> to be if the proponent of the feature feels strongly enough about the
> need for it
> to make it work and there aren't serious objections, in it goes. I
> think that the
> current ability to assign a coderef to a scalar is sufficient for all
> possible use
> cases,

Someone who does Perl training for a living can probably answer this more
definitively but a common newbie question is "how do I declare a lexical
subroutine?" (or local or private or whatever) and they're often quite
surprised when "my sub foo" doesn't work and weirded out by "my $foo = sub".

"my sub foo" makes sense. If you already understand lexical scope you don't
have to explain it. You don't have to wonder about it. Rather than
confusing things it will make them simpler. Rather than add a special case
it eliminates one. How do you declare a lexical variable? You put "my" in
front of the declaration. How do you declare a lexical subroutine? Same
answer.

On the contrary, "my $private = sub" and "$private->($obj, @args)" and
"$obj->$private(@args)" are different and confusing. It took us HOW many
years to think of that? 5? 10? You show someone "my $code = sub" and all
the special attendant syntax and they wonder what in the hell is going on.
Every time I've introduced that idea to a new shop I've gotten questions,
confusion and push back.

Real lexical subs line up beautifully with the rest of the lexical system.
Its a missing piece.


> and the additional decoration on the resulting calls is a good
> thing as
> it makes lexically scoped routines look different.

By this argument, and I believe Abigail pointed this out several times,
there should be a different syntax for using lexical variables than global
variables.

And who knows, maybe there should be. Ruby does it, I think. But that's
Ruby, this is Perl, and we don't make lexicals look different and its a
little late in the game to start.


> And $name->(ARGLIST)
> does not look like a method call to my eyes. A method call looks like
> $name->method(ARGLIST) -- notice the token between the arrow and the (.

You know that $object->$coderef(@args) works?

$ perl -wle 'my $private = sub { join "\n", @_ }; $o = bless {}; print
$o->$private(42)'
main=HASH(0x1801180)
42

Demerphq

unread,
Mar 9, 2007, 3:20:28 PM3/9/07
to Michael G Schwern, Mark Jason Dominus, Perl5 Porters

I think the issue that MJD was alluding to was that it is reasonable
to assume that the fib() calls in the lexically scoped fib() will
actually reference the dynamically scoped fib() because the lexically
scoped fib() wont be defined at the time the content of the sub is
compiled. And that changing this behaviour probably has deeper
ramifications than appear at first glance.


>
> And this will die.
>
> sub fib { die }
>
> {
> fib(5);
>
> my sub fib {
> my $n = shift;
> return $n < 2 ? $n : fib($n-1) + fib($n-2);
> };
> }

If you assume that

my sub foo {..};

is the same as

local *foo=*foo;
*foo=sub{...};

then the interpretation given here is reasonable. But then you have
problems elsewhere such as with

sub foo { print 1 }
sub bar { foo() }

{
my sub foo { print 2 };
bar();
}

which would print 2. But most people seem to expect that the above
should print 1.

So you then have a problem in that you either have to change the rule
about when the sub declaration comes into effect so that the lexical
sub declaration is valid before the sub body is parsed, or you have a
problem that it just simulates localization.

Abigail

unread,
Mar 9, 2007, 3:48:35 PM3/9/07
to Jan Dubois, Michael G Schwern, Mark Jason Dominus, Perl5 Porters
On Fri, Mar 09, 2007 at 12:19:51PM -0800, Jan Dubois wrote:
> On Fri, 09 Mar 2007, Michael G Schwern wrote:
> > This will recurse into the lexical fib() routine.
> >
> > sub fib { die }
> >
> > {
> > my sub fib {
> > my $n = shift;
> > return $n < 2 ? $n : fib($n-1) + fib($n-2);
> > };
> >
> > fib(5);
> > }
>
> Nope, this should die too (in the first recursive call). Any calls to
> fib() from inside the lexical function will not result in recursion but
> call the function visible in the outer scope. This has to be consistent
> with usage like this:
>
> $x = 10;
> {
> my $x = $x + 1;
> print $x;
> }
>
> This has to print 11 and not 1 because the right hand side of the
> assignment to the lexical still references the variable from the
> outer scope.
>
> This make the lexical sub form unsuitable for recursive function.

Is that true?

sub fib {
my $n = shift;
return $n < 2 ? $n : fib($n-1) + fib($n-2);
}

works without a problem. It's only problematic if you leave the parens
off when calling fib() - then you need the forward declaration.

So why would it be different with a lexical sub?

>
> You could work around it by allowing:
>
> my sub fib;
> my sub fib { ... fib() } ;
>
> This is still inconsistent with the way multiple "my" declarations
> work for other variables.


Yes, to make it consistent, you would write it as:

my sub fib;
sub fib { ... fib() };

Abigail

Mark Jason Dominus

unread,
Mar 9, 2007, 3:47:22 PM3/9/07
to perl5-...@perl.org
demerphq <deme...@gmail.com>:

> I think the issue that MJD was alluding to was that it is reasonable
> to assume that the fib() calls in the lexically scoped fib() will

No, not really.

The issue that I was alluding to is that the semantics are not totally
clear and that there are a bunch of edge cases that would need to be
considered IF someone were to do an implementation.

And that I have a large supply of code here that could be used to test
such edge cases.

The rest of you guys are all just showing off your l33t sk1llz at
writing "fizz buzz" programs.

David Nicol

unread,
Mar 9, 2007, 4:01:19 PM3/9/07
to Michael G Schwern, Perl5 Porters
On 3/9/07, Michael G Schwern <sch...@pobox.com> wrote:

> Someone who does Perl training for a living can probably answer this more
> definitively but a common newbie question is "how do I declare a lexical
> subroutine?" (or local or private or whatever) and they're often quite
> surprised when "my sub foo" doesn't work and weirded out by "my $foo = sub".

And a good answer to that might be "You can do them but it's complex
and ugly. Do you really need them?" That's the way things are with
aliaing through l-value reference syntax -- it too is a missing piece
with absence strange to C++ programmers, as lexical subs is a missing
piece with absence strange to Pascal programmers (and whoever else
expects them to be there.)

> Real lexical subs line up beautifully with the rest of the lexical system.
> Its a missing piece.

Sure it's a missing piece, but we've gotten by without it for this long, and
there are available workarounds for when you Really Need It. Just like
proposed l-value reference syntax shorthand for Devel::Lexalias. I doubt
that the OP will create enough buzz to cause some Other Person to
do the implementation.

> > And $name->(ARGLIST)
> > does not look like a method call to my eyes. A method call looks like
> > $name->method(ARGLIST) -- notice the token between the arrow and the (.
>
> You know that $object->$coderef(@args) works?

Why anyone would write that instead of $coderef->($object, @args) is a mystery
to me. the scalar in the $coderef spot can also hold a method name, right?

Larry Wall

unread,
Mar 9, 2007, 4:39:17 PM3/9/07
to perl5-...@perl.org
On Fri, Mar 09, 2007 at 03:47:22PM -0500, Mark Jason Dominus wrote:
: The issue that I was alluding to is that the semantics are not totally

: clear and that there are a bunch of edge cases that would need to be
: considered IF someone were to do an implementation.
:
: And that I have a large supply of code here that could be used to test
: such edge cases.
:
: The rest of you guys are all just showing off your l33t sk1llz at
: writing "fizz buzz" programs.

[This is addressed to everyone, not specifically to MJD.]

If someone wants to show off their 1334 cross-language 6ki1z they could
translate those test cases to Perl 6 and install them into the pugs
test repository, since pugs already purports to handle lexically scoped
subs. We've already dealt with at least some of these issues, though
perhaps not always in a way that is amenable to a Perl 5 retrofit,
since Perl 6 can rely on its simplified rules of lexical scoping here.

I'm really under little illusion that the features added to Perl 5
will tend to converge towards the Perl 6 design. It would be nice
if they could, but all you have to do is read the 361 RFCs that
were written in 2000 to see how they're pulling in lots of mutually
contradictory directions, each with its own form of tunnel vision.
Then look at the same forces of divergence still in effect today,
with lots of people just trying to fix one of the problems while
ignoring all the other problems that interfere with a sane solution.
And don't take me wrong; there's nobody to point a finger at here
other than myself for the suboptimal design decisions of the past.
I don't mind taking responsibility for that part. :)

I think Perl 5 still has a lot of life left in it, like an aging star.
And given a choice, I'd prefer to see Perl 5 to age gracefully into
a white dwarf rather than a supernova. But whether the whole thing
explodes or not, that will be the community's choice, not mine. And
after all, there's also something to be said for cultural supernovas
by those of us formed from the ashes of past such explosions.

So whether or not things explode, just keep remembering that people
are more important than things, and keep reminding the rest of us
when we forget. Thanks.

Larry

Michael G Schwern

unread,
Mar 9, 2007, 5:22:40 PM3/9/07
to David Nicol, Perl5 Porters
David Nicol wrote:
>> Real lexical subs line up beautifully with the rest of the lexical
>> system.
>> Its a missing piece.
>
> Sure it's a missing piece, but we've gotten by without it for this long,
> and there are available workarounds for when you Really Need It.

And if it gets implemented we won't have to work around it any longer. Hurray!


>> > And $name->(ARGLIST)
>> > does not look like a method call to my eyes. A method call looks like
>> > $name->method(ARGLIST) -- notice the token between the arrow and
>> the (.
>>
>> You know that $object->$coderef(@args) works?
>
> Why anyone would write that instead of $coderef->($object, @args) is a
> mystery to me.

The same reason I wouldn't write _private($object, @args); [1] Its just a
hack to have real private methods, so it should look as much like a method
call as possible. I don't have to guess why a code ref is being used.

Consider what a normal private method call looks like:

sub _secret { ... }

$obj->_secret(@args);

The hack conveys its intentions by looking similar.

my $secret = sub { ... };

$obj->$secret(@args);

Maybe you want to go a step further and call it $_secret. YMMV.


> the scalar in the $coderef spot can also hold a method name, right?

Yes.

[1] Yes, I know, there's accidental inheritance concerns with
$obj->_private(@args) which _private($obj, @args) avoids.

Michael G Schwern

unread,
Mar 9, 2007, 5:28:02 PM3/9/07
to demerphq, Mark Jason Dominus, Perl5 Porters
demerphq wrote:
> If you assume that
>
> my sub foo {..};
>
> is the same as
>
> local *foo=*foo;
> *foo=sub{...};

Wait, that's not right at all. That means...

{
my sub foo { 42 }

bar();
}

sub bar {
print foo();
}

Would print 42. That's not lexical at all, that's a temp function.

Compare with this which is the equivalent in current code:

{
my $foo = sub { 42 };

bar();
}

sub bar {
print $foo->();
}

That wouldn't work.

Dr.Ruud

unread,
Mar 9, 2007, 5:52:01 PM3/9/07
to perl5-...@perl.org
"H.Merijn Brand" schreef:

> Now that we have lexical $_, why not lexical subs

See also Class::Std's :PRIVATE().

--
Affijn, Ruud

"Gewoon is een tijger."

Demerphq

unread,
Mar 10, 2007, 4:21:16 AM3/10/07
to Michael G Schwern, Mark Jason Dominus, Perl5 Porters
On 3/9/07, Michael G Schwern <sch...@pobox.com> wrote:
> demerphq wrote:
> > If you assume that
> >
> > my sub foo {..};
> >
> > is the same as
> >
> > local *foo=*foo;
> > *foo=sub{...};
>
> Wait, that's not right at all. That means...
>
> {
> my sub foo { 42 }
>
> bar();
> }
>
> sub bar {
> print foo();
> }
>
> Would print 42. That's not lexical at all, that's a temp function.

Yes I said that as well. In fact it was the point of my reply.

The interpretation you gave contradicted the behavior of other lexical
declarations and the only way i could reconcile that interpretation
was to offer the localized sub interpretation, which as I pointed out
leads to its own problems.

> Compare with this which is the equivalent in current code:
>
> {
> my $foo = sub { 42 };
>
> bar();
> }
>
> sub bar {
> print $foo->();
> }
>
> That wouldn't work.

Right but assuming that a lexically scoped recursive subroutine
behaves this way would either make recursive lexical subroutines
impossible, or involve changing how my sub declarations and how
subroutine calls in their bodies are resolved at compile time.

In other words i was making much the same point as Jan did.

Cheers,

Demerphq

unread,
Mar 10, 2007, 4:25:07 AM3/10/07
to perl5-...@perl.org
On 3/9/07, Mark Jason Dominus <m...@plover.com> wrote:
> demerphq <deme...@gmail.com>:
> > I think the issue that MJD was alluding to was that it is reasonable
> > to assume that the fib() calls in the lexically scoped fib() will
>
> No, not really.
>
> The issue that I was alluding to is that the semantics are not totally
> clear and that there are a bunch of edge cases that would need to be
> considered IF someone were to do an implementation.

Hmm, i thought that was what i said pretty much. I guess it wasnt clear. Sorry.

> And that I have a large supply of code here that could be used to test
> such edge cases.
>
> The rest of you guys are all just showing off your l33t sk1llz at
> writing "fizz buzz" programs.

I thought we were trying to figure out what semantics were required to
have a sane implementation. And personally, I dont even know what
"fizz buzz" programs are.

Demerphq

unread,
Mar 10, 2007, 4:29:40 AM3/10/07
to Abigail, Perl5 Porters

Because fib(...) is essentially the same as *fib{CODE}->(...), so its
doing a symbolic reference to a global. Thus it doesnt matter that its
not defined at the time the sub body is compiled. Wheras with a truely
lexically scoped sub I dont think it can use a symbolic reference to
avoid the problem.

> >
> > You could work around it by allowing:
> >
> > my sub fib;
> > my sub fib { ... fib() } ;
> >
> > This is still inconsistent with the way multiple "my" declarations
> > work for other variables.
>
>
> Yes, to make it consistent, you would write it as:
>
> my sub fib;
> sub fib { ... fib() };

If that was possible then it would be a good resolution to the
recursion problem IMO.

Larry Wall

unread,
Mar 10, 2007, 11:51:16 AM3/10/07
to demerphq, Michael G Schwern, Mark Jason Dominus, Perl5 Porters
On Sat, Mar 10, 2007 at 10:21:16AM +0100, demerphq wrote:
: Right but assuming that a lexically scoped recursive subroutine

: behaves this way would either make recursive lexical subroutines
: impossible, or involve changing how my sub declarations and how
: subroutine calls in their bodies are resolved at compile time.

Bingo. The problem is really in the timing of name introduction to
the current lexical scope. This is why Perl 6 always consistently
introduces the name as soon as the name is seen rather than at the end
of the current statement or declaration. It's probably too late to
retrofit that to current Perl 5 sub definitions, but lexical subs could
be a special case that does it right, or at least righter. (Perl 6
goes a bit further in the lexical area by requiring all unqualified
instances of the same name within a lexical scope to resolve to the
same thing, and by forcing all unrecognized barewords to be parsed
conjecturally as list ops that must be bound to a sub by the end of
the compilation unit or fail. Together these make it fairly easy to
write mutually recursive lexical subs without a lot of predeclaration.)

Larry

Michael G Schwern

unread,
Mar 10, 2007, 6:07:12 PM3/10/07
to Larry Wall, demerphq, Mark Jason Dominus, Perl5 Porters
Larry Wall wrote:
> It's probably too late to
> retrofit that to current Perl 5 sub definitions, but lexical subs could
> be a special case that does it right, or at least righter.

There's precedent for this sort of lexical declaration heuristics:

use strict;

if( my $thing = foo() ) { # condition pretends its inside the block
print $thing;
}

print $thing; # *bzzzt*

I don't think anyone would be surprised if lexical subs did something similar.

Dr.Ruud

unread,
Mar 10, 2007, 9:11:54 PM3/10/07
to perl5-...@perl.org
Michael G Schwern schreef:

> if( my $thing = foo() ) { # condition pretends its inside the block

I often explained it as: there is an implicit block around the
"if(...){}elseif(...){}else{}". But such an "extra block" might also not
be the best way to explain it. :)

H.Merijn Brand

unread,
Mar 11, 2007, 4:55:27 AM3/11/07
to perl5-...@perl.org
On Sat, 10 Mar 2007 15:07:12 -0800, Michael G Schwern <sch...@pobox.com>
wrote:

> Larry Wall wrote:

The context never has been clear to me anyway:

nb09:/home/merijn 105 > perl -wle'if (my $x = 3) { print $x }'
Found = in conditional, should be == at -e line 1.
3
nb09:/home/merijn 106 > perl -wle'my $x = 3 and print $x'
Found = in conditional, should be == at -e line 1.
Name "main::x" used only once: possible typo at -e line 1.
Use of uninitialized value in print at -e line 1.

nb09:/home/merijn 107 > perl -wle'sub foo { 3 } my $x = foo () and print $x'
Name "main::x" used only once: possible typo at -e line 1.
Use of uninitialized value in print at -e line 1.

nb09:/home/merijn 108 >


Explain that to users.

--
H.Merijn Brand Amsterdam Perl Mongers (http://amsterdam.pm.org/)
using & porting perl 5.6.2, 5.8.x, 5.9.x on HP-UX 10.20, 11.00, 11.11,
& 11.23, SuSE 10.0 & 10.2, AIX 4.3 & 5.2, and Cygwin. http://qa.perl.org
http://mirrors.develooper.com/hpux/ http://www.test-smoke.org
http://www.goldmark.org/jeff/stupid-disclaimers/

Michael G Schwern

unread,
Mar 11, 2007, 5:43:55 AM3/11/07
to H.Merijn Brand, perl5-...@perl.org
H.Merijn Brand wrote:
> The context never has been clear to me anyway:
>
> nb09:/home/merijn 105 > perl -wle'if (my $x = 3) { print $x }'
> Found = in conditional, should be == at -e line 1.
> 3
> nb09:/home/merijn 106 > perl -wle'my $x = 3 and print $x'
> Found = in conditional, should be == at -e line 1.
> Name "main::x" used only once: possible typo at -e line 1.
> Use of uninitialized value in print at -e line 1.
>
> nb09:/home/merijn 107 > perl -wle'sub foo { 3 } my $x = foo () and print $x'
> Name "main::x" used only once: possible typo at -e line 1.
> Use of uninitialized value in print at -e line 1.
>
> nb09:/home/merijn 108 >
>
>
> Explain that to users.

Its not clear what part you mean, but I'm going to assume you mean the
lexical scope of $x and not the other warnings. Well that's just wrong and
unrelated to the "conditional inside the block" hack.

$ perl -wle 'use strict; sub foo { 3 } my $x = foo and print $x'
Global symbol "$x" requires explicit package name at -e line 1.
Execution of -e aborted due to compilation errors.

Which is to say:

$ perl -MO=Deparse -le 'my $x = "foo" and print $x'
BEGIN { $/ = "\n"; $\ = "\n"; }
print $x if my $x = 'foo';
-e syntax OK

Its an unfortunate consequence of the way "foo and/or bar" is implemented
and should probably be considered a bug, not a feature.

David Nicol

unread,
Mar 12, 2007, 1:21:52 PM3/12/07
to Michael G Schwern, H.Merijn Brand, perl5-...@perl.org
Short way to make scalar coderef lexical subroutines look nicer:

Allow the first of these three to work; possibly also implying
execution of coderefs in void context (no not that; it would
open a huge can of edge case worms -- or would it?)

# perl -wle '$x=sub{print 22}; $x()'
syntax error at -e line 1, near "$x("


Execution of -e aborted due to compilation errors.

# perl -wle '$x=sub{print 22}; &$x'
22
# perl -wle '$x=sub{print 22}; &$x()'
22

H.Merijn Brand

unread,
Mar 12, 2007, 1:47:48 PM3/12/07
to David Nicol, Michael G Schwern, perl5-...@perl.org
On Mon, 12 Mar 2007 11:21:52 -0600, "David Nicol" <david...@gmail.com>
wrote:

> Short way to make scalar coderef lexical subroutines look nicer:
>
> Allow the first of these three to work; possibly also implying
> execution of coderefs in void context (no not that; it would
> open a huge can of edge case worms -- or would it?)
>
> # perl -wle '$x=sub{print 22}; $x()'
> syntax error at -e line 1, near "$x("

Good. If this is just to support the drop of the ->, I don't mind

> Execution of -e aborted due to compilation errors.
> # perl -wle '$x=sub{print 22}; &$x'
> 22
> # perl -wle '$x=sub{print 22}; &$x()'
> 22

Rafael Garcia-Suarez

unread,
Mar 12, 2007, 2:22:13 PM3/12/07
to H.Merijn Brand, David Nicol, Michael G Schwern, perl5-...@perl.org
On 12/03/07, H.Merijn Brand <h.m....@xs4all.nl> wrote:
> On Mon, 12 Mar 2007 11:21:52 -0600, "David Nicol" <david...@gmail.com>
> wrote:
>
> > Short way to make scalar coderef lexical subroutines look nicer:
> >
> > Allow the first of these three to work; possibly also implying
> > execution of coderefs in void context (no not that; it would
> > open a huge can of edge case worms -- or would it?)
> >
> > # perl -wle '$x=sub{print 22}; $x()'
> > syntax error at -e line 1, near "$x("
>
> Good. If this is just to support the drop of the ->, I don't mind

Doesn't feel consistent with

$ perl -wle '$x=[22]; print $x[0]'


Use of uninitialized value in print at -e line 1.

$ perl -wle '$x=[22]; print @$x[0]'
22

David Nicol

unread,
Mar 12, 2007, 3:36:17 PM3/12/07
to Perl 5 Porters
I am sorry this is incoherent notes; I believe incoherent notes are
defensible at this stage. Be warned: incoherent, and contradictory,
notes, follow.


On 3/12/07, Rafael Garcia-Suarez <rgarci...@gmail.com> wrote:
> > > # perl -wle '$x=sub{print 22}; $x()'

> Doesn't feel consistent with


>
> $ perl -wle '$x=[22]; print $x[0]'
> Use of uninitialized value in print at -e line 1.
>
> $ perl -wle '$x=[22]; print @$x[0]'
> 22

because SCALAR SQUAREBRACKETS already means something.
Since the "juxtaposition" operator has been vetoed, butting round
parens up against something is allowed. We don't have any more
dereferenced meaning for "live" scalars than "the coderef" -- a case
could be made that what we call a coderef, calling it a reference is
due to an implementation detail rather than adherence to a well-defined
semantics. Taking the value of a member of a container is done
by applying the name of the container, the kind of brackets, and then
the index. Code can be thought of the same way (and even
used the same way with Tie::Function if you want) but I need to
more explicitly dereference a CODE scalar -- with an arrow --

maybe lexical sub syntax should bring back the ampersand?

my &foo { ...


somewhere the line between data and code must be explicitly drawn.


Perhaps the arrowless parentheses syntax might even have a "symbolic
reference" kind of twist, implying a string-eval when applied to a
string?

"print shift"(22)

would be the same as

(sub {print shift})->(22)


Your at-large damaged brain cell,
David Nicol

Michael G Schwern

unread,
Mar 12, 2007, 7:56:02 PM3/12/07
to Rafael Garcia-Suarez, H.Merijn Brand, David Nicol, perl5-...@perl.org

I'm with Rafael here. If $x(@args) means "dereference $x as a code ref and
pass in @args" then $x[1] should mean "dereference $x as an array ref and
get index 1" and $x{foo} should mean "deref $x has a hash ref and get key foo".

It would be a good idea if all the rest worked that way, and I believe
that's how Perl 6 is doing it, but they don't in Perl 5 and it produces a
weird inconsistency.

Rick Delaney

unread,
Mar 12, 2007, 8:19:22 PM3/12/07
to Michael G Schwern, Rafael Garcia-Suarez, H.Merijn Brand, David Nicol, perl5-...@perl.org
On Mar 12 2007, Michael G Schwern wrote:
> I'm with Rafael here. If $x(@args) means "dereference $x as a code ref and
> pass in @args" then $x[1] should mean "dereference $x as an array ref and
> get index 1" and $x{foo} should mean "deref $x has a hash ref and get key foo".

It's a non-starter anyway.

print $fh(41 + 1);

cannot mean

print $fh->(42);

because it already means

print $fh 42;

.

--
Rick Delaney
ri...@bort.ca

Johan Vromans

unread,
Mar 13, 2007, 4:18:46 AM3/13/07
to Rick Delaney, Michael G Schwern, Rafael Garcia-Suarez, H.Merijn Brand, David Nicol, perl5-...@perl.org
Rick Delaney <ri...@bort.ca> writes:

> print $fh(41 + 1);
> cannot mean
> print $fh->(42);
> because it already means
> print $fh 42;

Oh, we can fix that by making the blanks significant.
<ducks quickly>

-- Johan

David Nicol

unread,
Mar 13, 2007, 11:57:30 AM3/13/07
to Michael G Schwern, perl5-...@perl.org
Executive summary:

I think what I may be saying in this longwinded and tortuous manner is
that when the ampersand was made optional a decade ago, not making
the ampersand optional on executable scalars may have been a missing piece.


On 3/12/07, Michael G Schwern <sch...@pobox.com> wrote:
> Rafael Garcia-Suarez wrote:
>> ...


> I'm with Rafael here. If $x(@args) means "dereference $x as a code ref and
> pass in @args" then $x[1] should mean "dereference $x as an array ref and
> get index 1" and $x{foo} should mean "deref $x has a hash ref and get key foo".
>
> It would be a good idea if all the rest worked that way, and I believe
> that's how Perl 6 is doing it, but they don't in Perl 5 and it produces a
> weird inconsistency.

Excellent. The point, or insight, from yesterday, which may be entirely bogus,
but which I was trying to convey or share, or trying to make, was, that coderefs
are different from containerrefs because they're not really refs --
they're already
as dereferenced as they can be without compiling them back to source or
executing them. So the change in norms would involve phasing out calling
the result of C<$x=sub{...}> a "coderef" and instead call it a "code
object." At
which point this objection based on consistency would go away. If $x is
a lexical (and therefore free from the syntaxtical goodness that is provided by
package globs) code object in a scalar, $x(@args) may make sense.

using package globs,

*packhash = {one=>1}; print $packhash{one};
*packarr = [one=>1]; print $packarr[1];
*packsub = sub {shift}; print packsub(1);

those will all print 1

but using scalars,


my $lexhash = {one=>1}; print $$lexhash{one};
my $lexarr = [one=>1]; print $$lexarr[1];
my $lexsub = sub {shift}; print &$lexsub(1);

I think what I may be saying in this longwinded and tortuous manner is
that when the ampersand was made optional a decade ago, not making
the ampersand optional on executable scalars may have been a missing piece.

Reply all
Reply to author
Forward
0 new messages