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).
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.
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.
> 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.
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.
David Storrs wrote: >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.
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
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 ().
> 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 ().
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.
> 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 ().
> 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.
> 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
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 m...@biggar.org mark.a.big...@attbi.com
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
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 ->?
David Storrs wrote: >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?
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.
>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 ->?
> 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)];
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")
> >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 ->?
--- Luke Palmer <fibon...@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???
__________________________________________________ Do you Yahoo!? The New Yahoo! Search - Faster. Easier. Bingo http://search.yahoo.com
> --- Luke Palmer <fibon...@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:
> >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?
> 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.
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:
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.
On Thu, Apr 17, 2003 at 12:18:43PM -0600, Luke Palmer wrote:
: > --- Luke Palmer <fibon...@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 : }
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.