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

pointy-subs and &_

0 views
Skip to first unread message

Dave Whipp

unread,
Apr 10, 2003, 10:31:12 PM4/10/03
to perl6-l...@perl.org
I was reading S6, and I realised:

sub foo
{
while ($a = $iter.next)
{
&_($a); # &_ is foo
}
}

sub bar
{
for @array -> $a
{
&_($a); # &_ is NOT bar
}
}

Yes, they're silly examples, but I'm sure that this could be very
confusing. It violates the principle of least surprise. (If we defined
that pointy-subs don't set &_, then they are no longer anon subs without
parens).


Dave.

Larry Wall

unread,
Apr 11, 2003, 2:07:56 PM4/11/03
to perl6-l...@perl.org
On Thu, Apr 10, 2003 at 07:31:12PM -0700, Dave Whipp wrote:
: I was reading S6, and I realised:

:
: sub foo
: {
: while ($a = $iter.next)
: {
: &_($a); # &_ is foo
: }
: }
:
: sub bar
: {
: for @array -> $a
: {
: &_($a); # &_ is NOT bar
: }
: }

This is incorrect. &_ refers to &bar here.

: Yes, they're silly examples, but I'm sure that this could be very

: confusing. It violates the principle of least surprise. (If we defined
: that pointy-subs don't set &_, then they are no longer anon subs without
: parens).

Pointy subs are variants of Block, not of Routine. In this sense
it is inaccurate to think of them as "anon subs without parens".
They're more like blocks with parameters. We only mention the
likeness to sub () {...} to explain how the parameters work. In
other respects pointy subs do not work the same.

Larry

David Storrs

unread,
Apr 16, 2003, 10:49:37 AM4/16/03
to perl6-l...@perl.org
On Fri, Apr 11, 2003 at 11:07:56AM -0700, Larry Wall wrote:

> Pointy subs are variants of Block, not of Routine. In this sense
> it is inaccurate to think of them as "anon subs without parens".
> They're more like blocks with parameters. We only mention the
> likeness to sub () {...} to explain how the parameters work. In
> other respects pointy subs do not work the same.
>
> Larry

Could we get a micro-Exegesis on -> vs sub? Specifically, what are
the differences? Why would I use one over the other? What new power
does -> add to the language? This is something that has confused me
for a long time, no matter how much I read the Apocalypse.


--Dks

Luke Palmer

unread,
Apr 16, 2003, 11:14:42 AM4/16/03
to dst...@dstorrs.com, perl6-l...@perl.org

Although my mind is running blank of an actual example, I can explain
some of the differences.

C<sub> is for a real subroutine, which you might give to a UI daemon
as a callback, or you might just call yourself. It binds &_ to
itself, and needs its parameter list enclosed in parens. Most often,
you won't make anonymous subs, you'll make named ones.

-> is specifically for anonymous closures. It's used to parameterize
some code that you might give to C<for> or C<map>. It doesn't bind
&_, and it doesn't need its parameter list enclosed in parens. You
can't make named ->'s.

->'s a lot more like another way to have a block with $^variables (or
just plain $_) in it, as opposed to a real subroutine. For instance,
C<for> (the thing it was made for, I think):

for @a -> $var {
print $var;
}

As opposed to:

for @a sub ($var) {
print $var;
}

So that bit's about readability. Plus, if you return from the top
one, you'll return whatever function you're in. If you return from
the bottom one, it'll be like doing a C<next> (because you just
returned from the inner block). Those can also be written as:

for @a {
print $^var;
}

for @a {
print;
}

Which both behave more like -> than like C<sub>.

So it's just a way to specify formal parameters to a block out in
front.

Luke

Buddha Buck

unread,
Apr 16, 2003, 11:54:24 AM4/16/03
to David Storrs, perl6-l...@perl.org
David Storrs wrote:

I'm not Larry, I'm not on the design team, but I'm certain that if there
are any errors in my summary, someone will leap on them.

First, let's talk about the differences and similarities between subs
and blocks:

Subs:
Lexically, look to the eye like a self-contained whole.
Are a closure.
Have a name.
Can return a value using the "return" keyword.
Can have parameters
Set &_ internally to itself (the calling sub)

Blocks:
Lexically, look to the eye like a part of a greater whole
Are a closure
Do not have names
Do not typically return a value
Are left using the "leave" keyword.

Anonymous Subs:
Lexically, look like a self-contained whole used as an expression.
Are a closure
Do not have names
Can return a value using the "return" keyword
Can have parameters
Set &_ internally to itself (the calling sub)

Pointy blocks:
Lexically, look to the eye like part of a greater whole
Are a closure
Do not have names
Do not typically return a value
Are left using the "leave" keyword.
Can have parameters

Syntax-wise, subs use the (simplified) syntax:

'sub' [name] [trait]* [([parameter [, parameter]*])] {...}

Because the name is optional and is otherwise unmarked, the parameter
list must be identified by parenthesis. Leave out the name, and you
have an anonymous sub.

Syntax-wise, blocks use the (simplified) syntax

[ '->' [parameter [,parameter]*] ] {...}

There is no other construct that begins with ->, so anything between the
-> and the { must be associated with the block, and serves as a place
for a parameter list, which doesn't require parenthesis. Use the
optional pointy-bit, and you have a pointy-block.

Or... in other words...

Subs are self-contained, and optionally have a name, return type, and
parameter lists. They bind &_ to themselves on execution, and exit with
a "return" keyword, optionally with a return value. Subs are called via
name, or via a sub reference stored in a variable. anonymous (unnamed)
subs can only be called via a sub reference (implicitly or explicitly).
Subs must be called to execute; mere declaration of a sub does not
execute it. Subs easily support recursion, either via a call to its own
name, or to a call to &_. Declaration of a named sub where Perl6 is
expecting a statement merely creates a new sub with that name.
Declaration of a sub (named or otherwise) where Perl6 is expecting an
expression created a new sub and returns a reference to it.

Blocks are part of a larger routine, and optionally have a parameter
list. They do not bind &_ on execution. You can exit a block with a
"leave" statement. They do not return any values, and have no return
type. Blocks are either executed implicitly, or via a closure reference
stored in a variable. Blocks do not easily support recursion. A block
where Perl6 is expecting a statement executes that block. A block where
Perl6 is expecting an expression creates a new block closure and returns
a reference to it.

A6 had a hierarchy of control structure types, and calls what I've
described as "subs" above as of type "Routine", which can be subs,
methods, rules, macros, multis, or submethods. All of which are
declared using a keyword. What I've called "blocks" are of type
"Block", which can be "bare" or "parameterized", which Larry isn't sure
is worth distinguising between, since a bare block is a block with a
parameter signature of ().

>
>
>--Dks
>
>

Luke Palmer

unread,
Apr 16, 2003, 12:09:55 PM4/16/03
to bmb...@14850.com, dst...@dstorrs.com, perl6-l...@perl.org
> Blocks are part of a larger routine, and optionally have a parameter
> list. They do not bind &_ on execution. You can exit a block with a
> "leave" statement. They do not return any values, and have no
> return type.

That's not necessarily true:

@b = map -> $a { $a**2 } @a;

That takes each I<return> of the pointy block and appends it to @b. I
don't think it's possible to I<declare> a return type, but you can
certainly return things.

> Blocks are either executed implicitly, or via a closure reference
> stored in a variable. Blocks do not easily support recursion.

Although because of the new name-introduction policy, you can now do
this:

my $fact = -> $n {
$n ?? $n * $fact.($n-1) :: 1
}

Without pre-declaring $fact. Yay!

> A block where Perl6 is expecting a statement executes that block. A
> block where Perl6 is expecting an expression creates a new block
> closure and returns a reference to it.

Yeah, I think that a block in void context in general automatically
executes. But I could be wrong about that.



> A6 had a hierarchy of control structure types, and calls what I've
> described as "subs" above as of type "Routine", which can be subs,
> methods, rules, macros, multis, or submethods. All of which are
> declared using a keyword. What I've called "blocks" are of type
> "Block", which can be "bare" or "parameterized", which Larry isn't sure
> is worth distinguising between, since a bare block is a block with a
> parameter signature of ().

Rather (?$_ = $OUTER::_).

Luke

David Storrs

unread,
Apr 16, 2003, 1:06:25 PM4/16/03
to perl6-l...@perl.org
On Wed, Apr 16, 2003 at 11:54:24AM -0400, Buddha Buck wrote:

> First, let's talk about the differences and similarities between subs
> and blocks:

Ok, this is useful. I'm going to clip out the bits about how it looks
to the eye, because I'm really trying to get a handle on how it
B<works>.

For clarity, I'd like to do a side-by-side comparison. First though,
I'd like to nitpick:

IIUC, subs (anon or named) B<always> return a value; either
explicitly, or the last value evaluated. I am less sure about blocks,
but based on the way a block passed to a sort() works, I would assume
that they behave the same. Please correct me if I'm wrong. I don't
know if this is the case for pointy blocks or not; in your
explanation, you said "typically do not", implying that they can.


> Subs: Are a closure.
> Anon Subs: Are a closure
> Blocks: Are a closure
> Pointy Blocks: Are a closure

> Subs: Can have parameters
> Anon Subs: Can have parameters
Blocks: Can have parameters [based on your comments below]
> Pointy Blocks: Can have parameters

Subs: Always return a value (explicitly, or the last value eval'd)
Anon. Subs: Always return a value (explicitly, or the last value eval'd)
Blocks: Always return a value (explicitly, or the last value eval'd) ??
Pointy Blocks: ???


So far, there is no fundamental difference between any of these
constructs.


> Subs: Have a name.
> Blocks: Do not have names
> Anon Subs: Do not have names
> Pointy Blocks: Do not have names


Subs: Are left using the "return" keyword
Anon Subs: Are left using the "return" keyword (I assume??)
> Blocks: Are left using the "leave" keyword.
> Pointy Blocks: Are left using the "leave" keyword.

> Subs: Set &_ internally to itself (the calling sub)
> Anon Subs: Set &_ internally to itself (the calling sub)
Blocks: Do not set &_ to themselves [based on your comments below]
Pointy Blocks: Do not set &_ to themselves [based on your comments below]


So, based on the above, the only real differences between these
constructs are:

1) Subs are the only thing that can take a name.

2) Subs (either flavor) are exited with C<return> while blocks (either
flavor) are exited with C<leave>.

3) Subs (either flavor) set &_ to themselves while blocks (either
flavor) do not.

I can't think, offhand, of any use for a named block [1] so I
understand the rationale for #1. #2 seems very arbitrary to me--why
the difference? I also don't understand the design decisions behind
#3. Why NOT set &_ (assuming that it's set as a temp var which
reverts to previous value on exit from the block)? This would allow
recursive blocks...is that something that @Larry was specifically
trying to avoid?

I have left the remainder of your comments below so that people can
verify my deductions above.

I really appreciate the clear explanation, Buddha. Thank you.


--Dks


[1] Unless you could pass it around and use it in multiple locations
without needing to make a subroutine call...hmmm.

Luke Palmer

unread,
Apr 16, 2003, 1:26:35 PM4/16/03
to dst...@dstorrs.com, perl6-l...@perl.org
> Subs: Always return a value (explicitly, or the last value eval'd)
> Anon. Subs: Always return a value (explicitly, or the last value eval'd)
> Blocks: Always return a value (explicitly, or the last value eval'd) ??
> Pointy Blocks: ???

Same. Pointy blocks are just blocks with signatures. Nothing more.

Yeah, blocks do return values. Whether or not they're used is up to
the caller.

> So, based on the above, the only real differences between these
> constructs are:
>
> 1) Subs are the only thing that can take a name.
>
> 2) Subs (either flavor) are exited with C<return> while blocks (either
> flavor) are exited with C<leave>.
>
> 3) Subs (either flavor) set &_ to themselves while blocks (either
> flavor) do not.
>
> I can't think, offhand, of any use for a named block [1] so I
> understand the rationale for #1. #2 seems very arbitrary to me--why
> the difference? I also don't understand the design decisions behind
> #3. Why NOT set &_ (assuming that it's set as a temp var which
> reverts to previous value on exit from the block)? This would allow
> recursive blocks...is that something that @Larry was specifically
> trying to avoid?

#2 is for this:

sub index(@stuff, $thing) {
my $ret = 0;
for @stuff {
return $ret when $thing; # Exits the sub, not the block
$ret++
}
}

#3, on a similar note, is for this:

sub recursive(@stuff) {
for @stuff -> $obj {
$obj.set_callback(&_)
}
}

(Or whatever)

I think the idea is to keep with the notion that blocks aren't
actually mini-subs (even though they may be implemented that way),
that they're just parts of subs. So when you do things that act on
the current sub, they act on what you think the current sub is.

Luke

Paul

unread,
Apr 16, 2003, 1:32:40 PM4/16/03
to David Storrs, perl6-l...@perl.org
> 2) Subs (either flavor) are exited with C<return> while blocks
> (either flavor) are exited with C<leave>.
>
> .... #2 seems very arbitrary to me--why the difference?

I think it's so that you can say

sub check_em {
for @_ {
return $_ if good_one($_);
}
}

that for is syntactic sugar for a pointy, isn't it?
Written more explicitly, that's:

sub check_em (*@_) {
for @_ -> $_ {
return $_ if good_one($_);
}
}

If I'm doing that right, it ought to at least explain one rationale.
I think the principle of least surprise would be violated if the return
in that loop just sent you to the next iteration of the loop...yes? :)

__________________________________________________
Do you Yahoo!?
The New Yahoo! Search - Faster. Easier. Bingo
http://search.yahoo.com

Mark Biggar

unread,
Apr 16, 2003, 1:52:48 PM4/16/03
to David Storrs, perl6-l...@perl.org
David Storrs wrote:

> 1) Subs are the only thing that can take a name.
>
> 2) Subs (either flavor) are exited with C<return> while blocks (either
> flavor) are exited with C<leave>.
>
> 3) Subs (either flavor) set &_ to themselves while blocks (either
> flavor) do not.
>
> I can't think, offhand, of any use for a named block [1] so I
> understand the rationale for #1. #2 seems very arbitrary to me--why
> the difference? I also don't understand the design decisions behind
> #3. Why NOT set &_ (assuming that it's set as a temp var which
> reverts to previous value on exit from the block)? This would allow
> recursive blocks...is that something that @Larry was specifically
> trying to avoid?

Both 2 and 3 are related ot the use of blocks as parts of larger
constructs like "if" statements. For 2, Larry wants to be able to
use a bare "return" statement in one branch of the "if" to mean
return from the "sub" enclosing the "if" not to mean just exit
the block, use "leave" for that. For 3, blocks as typically use
for structural stuff are not recursive (and probably shouldn't be)
which is what setting "&_" for the block would do. But "sub"s
do want to be recursive, and so set "&_", which allows the use
of "&_" in a branch of an "if" statement to mean the enclosing
"sub" and to recursively call that "sub" there with out the block
interfering.

--
Mark Biggar
ma...@biggar.org
mark.a...@attbi.com

Larry Wall

unread,
Apr 16, 2003, 2:24:51 PM4/16/03
to perl6-l...@perl.org
On Wed, Apr 16, 2003 at 11:54:24AM -0400, Buddha Buck wrote:
: Syntax-wise, subs use the (simplified) syntax:

:
: 'sub' [name] [trait]* [([parameter [, parameter]*])] {...}

By the by, the traits come after the sig.

Larry

Paul

unread,
Apr 16, 2003, 2:52:41 PM4/16/03
to Larry Wall, perl6-l...@perl.org

Ok, I've seen this bite several people, and I expect to be one of them
any day now. The correct structure is

sub foo () is bar {...}

right?

but I *keep* trying to say

sub foo is bar () {...}

Now, if there *were* no explicit sig,

sub foo is bar {...}

that would be ok, right?

I've just got to remember to think of the sig as part of the function
name...

Hey, how about this:

multi foo ($me, Int $i) returns Bar {...}
multi foo ($me, Str $s) returns Baz {...}
multi foo ($me) returns Glarchimous {...}

Does that work? (would I want it to? :)

Dave Whipp

unread,
Apr 16, 2003, 10:25:13 PM4/16/03
to perl6-l...@perl.org
David Storrs wrote:

> I can't think, offhand, of any use for a named block

...
{
...
MY_LABEL: {
...
{
...
leave where=>MY_LABEL;
...
}
...
}
}

Is the label associated with the block?


Dave.

Uri Guttman

unread,
Apr 16, 2003, 11:51:26 PM4/16/03
to Dave Whipp, perl6-l...@perl.org
>>>>> "DW" == Dave Whipp <da...@whipp.name> writes:

DW> David Storrs wrote:
>> I can't think, offhand, of any use for a named block

DW> ...
DW> {
DW> ...
DW> MY_LABEL: {
DW> ...
DW> {
DW> ...
DW> leave where=>MY_LABEL;
DW> ...
DW> }
DW> ...
DW> }
DW> }

DW> Is the label associated with the block?

wouldn't good ol' last MY_LABEL be good enough for that?

my impression is that leave is meant mostly for blocks passed as code
refs like with grep/map. leave will exit early and with a value that can
be used by the calling code. return would return out of the enclosing
real sub which is not what you want.

now, with nested blocks i don't know what would happen. i just can't
come up with a quick example of that sort of passed in code block.

uri

--
Uri Guttman ------ u...@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org

David Storrs

unread,
Apr 17, 2003, 11:25:59 AM4/17/03
to perl6-l...@perl.org
On Wed, Apr 16, 2003 at 09:14:42AM -0600, Luke Palmer wrote:

> Although my mind is running blank of an actual example, I can explain

> some of the differences. [ between -> and sub ]


>
> C<sub> is for a real subroutine, which you might give to a UI daemon
> as a callback, or you might just call yourself. It binds &_ to
> itself, and needs its parameter list enclosed in parens. Most often,
> you won't make anonymous subs, you'll make named ones.

Ok, got it.


> -> is specifically for anonymous closures. It's used to parameterize
> some code that you might give to C<for> or C<map>. It doesn't bind
> &_, and it doesn't need its parameter list enclosed in parens. You
> can't make named ->'s.

Why doesn't it bind &_? I'm not disagreeing, I just want to
understand the design decision.


> ->'s a lot more like another way to have a block with $^variables (or
> just plain $_) in it, as opposed to a real subroutine. For instance,
> C<for> (the thing it was made for, I think):
>
> for @a -> $var {
> print $var;
> }
>
> As opposed to:
>
> for @a sub ($var) {
> print $var;
> }

> So that bit's about readability. Plus, if you return from the top
> one, you'll return whatever function you're in. If you return from
> the bottom one, it'll be like doing a C<next> (because you just
> returned from the inner block).

Well, that makes sense with the whole 'sub' is a subroutine, '->' is a
block idea. Ok, I get it.


> Those can also be written as:
>
> for @a {
> print $^var;
> }
>
> for @a {
> print;
> }

Both of which seem more readable to me than the -> version.

I remain unconvinced that -> really adds much to the language. It
seems like one more construct that we need to learn, understand the subtle
differences of, and explain to newbies. I guess it does allow us to
pass a parameterized block around, which is maybe useful, but at that
point, why not just use a sub?

I really feel like I must be missing something here...@Larry are smart
folks, so the chances that they put something totally unnecessary in
are asymptotically close to zero; if I don't get it, it's probably my
failing, not theirs. Can someone show me some non-trivial code that
is made significantly easier to write AND maintain because of the
existence of ->?

--Dks

Buddha Buck

unread,
Apr 17, 2003, 1:23:18 PM4/17/03
to David Storrs, perl6-l...@perl.org
David Storrs wrote:

If you can get a reference to a block, it allows the ability to treat
control structures as functions, and thus they can be defined at
run-time. If you want to be able to treat control structures as
functions, you can't do that as easily -- you'd always have to pass in a
sub.

sub reversedfor (@array is rw, &block(Scalar), ?$index = @array-1) {
return if $index < 1;
block(@array[$index]); # or is that &block(@array[$index]); ???
reversedfor (@array, block, $index-1); # or is that ... &block ...?
}

# reversedfor can be used like:

reversedfor (1..10) {
print "$_";
}

# and will print "10 9 8 7 6 5 4 3 2 1"

If {...} didn't create an array reference of somesort, then you'd have
to call it like:

reversedfor (1..10), sub { print $_; }

and it wouldn't look like a replacement for "for".

Parameterized blocks give the ability to allow blocks to take multiple,
named arguments, without having to explictly create a sub. That allows
parameterized blocks to Xppear where you might expect a block to go:

sort { ^$b cmp ^$a } @datastream;

(sort defined as follows:

sub sort (&comparison(Scalar, Scalar), *@itemstosort)
{
my sub comp ($a, $b) { my $c = comparison($a, $b); return 0 if $c < 0;
return 2 if $c > 0; return 1; };
my @sublist = [[],[],[]];
my $pivot = @itemstosort[int(rand @itemstosort)];

for @itemstosort {
push @sublist[comp($pivot,$_);
}
@sublist[0] = sort comparison @sublist[0];
@sublist[2] = sort comparison @sublist[0];
return (*@sublist); # this will completely flatten sublist, right?
}

Note I said ^$b cmp ^$a, which reverses the normal sense of comparison.
I took advantage of the fact that for that style of parameterizing
blocks, the parameters are passed in alphabetically. But sometimes I
don't want to do that. Sometimes other orders are necessary.

method PasswordFile::selectrows ( Bool &selector(Str, Int, Str) ) {
my @results;
for @row {
push @results if selector(.name, .id, .homedir);
}
}

my PasswordFile passwd = PasswordFile.new("/etc/passwd")

@selection = $passwd.selectrows { (^$name ~ /root/ ||^$homedir ~
/rootdir/) && $^id != 0 };
## doesn't work, since name, id, and homedir not passed in in homedir,
id, name order.

@selection = $passwd.selectrows -> $name, $id, $homedir {
($name ~ /root/ || $ homedir ~ /rootdir/) && $id != 0;
}
## works.

(Assuming that ~ is smart-match. I don't remember offhand if its ~ or ~~)

Luke Palmer

unread,
Apr 17, 2003, 1:44:06 PM4/17/03
to bmb...@14850.com, dst...@dstorrs.com, perl6-l...@perl.org
> Parameterized blocks give the ability to allow blocks to take multiple,
> named arguments, without having to explictly create a sub. That allows
> parameterized blocks to Xppear where you might expect a block to go:
>
> sort { ^$b cmp ^$a } @datastream;

That's:

sort { $^b cmp $^a } @datastream;

> (sort defined as follows:
>
> sub sort (&comparison(Scalar, Scalar), *@itemstosort)
> {
> my sub comp ($a, $b) { my $c = comparison($a, $b); return 0 if $c < 0;
> return 2 if $c > 0; return 1; };
> my @sublist = [[],[],[]];
> my $pivot = @itemstosort[int(rand @itemstosort)];
>
> for @itemstosort {
> push @sublist[comp($pivot,$_);
> }
> @sublist[0] = sort comparison @sublist[0];
> @sublist[2] = sort comparison @sublist[0];

I think that's probably:

sort &comparison @sublist[0];

Lest you call comparison trying to pass it @sublist[0] as an argument
(and getting an error).

> return (*@sublist); # this will completely flatten sublist, right?

Don't believe so. * flattens outward, and I don't know what flattens
inward. I don't recall whether ** does that, or whether that's just
an eager outward flatten.

> }
>
> Note I said ^$b cmp ^$a, which reverses the normal sense of comparison.
> I took advantage of the fact that for that style of parameterizing
> blocks, the parameters are passed in alphabetically. But sometimes I
> don't want to do that. Sometimes other orders are necessary.
>
> method PasswordFile::selectrows ( Bool &selector(Str, Int, Str) ) {
> my @results;
> for @row {
> push @results if selector(.name, .id, .homedir);
> }
> }
>
> my PasswordFile passwd = PasswordFile.new("/etc/passwd")
>
> @selection = $passwd.selectrows { (^$name ~ /root/ ||^$homedir ~
> /rootdir/) && $^id != 0 };

You messed up the parens on this one:

@selection = $passwd.selectrows({ ... })

Method calls need parens. And that's $^name, etc.

> ## doesn't work, since name, id, and homedir not passed in in homedir,
> id, name order.
>
> @selection = $passwd.selectrows -> $name, $id, $homedir {
> ($name ~ /root/ || $ homedir ~ /rootdir/) && $id != 0;
> }
> ## works.

Can't have space between $ and homedir.

Ugh,

$passwd.selectrows(-> $name, $id, $homedir { ... })

Is getting ugly. Best go with:

selectrows $passwd: -> $name, $id, $homedir { ... };

> (Assuming that ~ is smart-match. I don't remember offhand if its ~ or ~~)

It's ~~. (At least you didn't say =~ :)

Paul

unread,
Apr 17, 2003, 2:10:25 PM4/17/03
to Luke Palmer, bmb...@14850.com, dst...@dstorrs.com, perl6-l...@perl.org

--- Luke Palmer <fibo...@babylonia.flatirons.org> wrote:
> > return (*@sublist); # this will flatten sublist, right?

>
> Don't believe so. * flattens outward, and I don't know what flattens
> inward. I don't recall whether ** does that, or whether that's just
> an eager outward flatten.

Inward? Outward?
Er???

Luke Palmer

unread,
Apr 17, 2003, 2:18:43 PM4/17/03
to Hod...@writeme.com, bmb...@14850.com, dst...@dstorrs.com, perl6-l...@perl.org
> --- Luke Palmer <fibo...@babylonia.flatirons.org> wrote:
> > > return (*@sublist); # this will flatten sublist, right?
> >
> > Don't believe so. * flattens outward, and I don't know what flattens
> > inward. I don't recall whether ** does that, or whether that's just
> > an eager outward flatten.
>
> Inward? Outward?
> Er???

Sorry, that wasn't clear.

[ *[a, [b, c], d], e]

evaluates to

[ a, [b, c], d, e ]

So sublists don't flatten. I call that "outward" flattening.
"Inward" flattening (assuming ** does that for the moment) would be:

[ **[a, [b, c], d], e ]

evaluates to

[ [ a, b, c, d], e ]

But it's probably more likely to go both ways, like:

[ a, b, c, d, e ]

A quick look at S6 deems this all irrelavent, as ** just flattens
eagerly. So to inward flatten, just use:

sub flatten($aref) {
map { *$_ } $aref
}

Luke

Austin Hastings

unread,
Apr 17, 2003, 2:30:57 PM4/17/03
to Buddha Buck, David Storrs, perl6-l...@perl.org

I think that @Larry may have fallen down at this point. Why is it that
C<map> and C<for> can use pointy subs, while C<if> and C<while> cannot?

If blockrefs are a performance win over subs, or if they have some
other benefit, I think I'd like to see them available as regular Code
objects for use in a lot of places:

class Object {
has Code %.vtable;

method dispatch($self: String $name, *@args) {
my &method = %.vtable{$name};
return &method($self, *@args);
}
}

or

my &cleanup = -> $status { return $status; };
...
my $fh = open ...
&cleanup += -> {$fh.close; }; # !!!
...
my $otherfile = open...
&cleanup += -> { $otherfile.close; };
...
{
...
CATCH { &cleanup; }
}

In this case, it's the answer to "here's why we need goto" arguments --
it's not a sub, it's cheap, and it can be used anywhere:

if $failure &cleanup;

(The notion of a Code variable being able to accumulate expressions to
execute is appealing, in a "Here, try a cigarette" fashion...)

> > I really feel like I must be missing something here...@Larry are
> > smart folks, so the chances that they put something totally
> > unnecessary in are asymptotically close to zero; if I don't get
> > it, it's probably my failing, not theirs. Can someone show me
> > some non-trivial code that is made significantly easier to
> > write AND maintain because of the existence of ->?

I think this is one of those cases where for @a -> $a { ...} has
implied the existence of ->$a { ...}, without having it well defined
yet.

=Austin

Larry Wall

unread,
Apr 17, 2003, 7:31:21 PM4/17/03
to perl6-l...@perl.org
: }

Er, I don't think * implies a dereference at all. It just forces
list context (and subverts scalar argument matching). True, arrays
autodeference themselves in a list context. But a [] in a list
context is still just a scalar array ref. Use @ if you want to deref
an array ref, just like in Perl 5.

Larry

0 new messages