Re: Clarification of S04 closure traits
Moritz Lenz wrote: Ben Morrow wrote: - Presumably when an exception is thrown through a block, the LEAVE and POST queues are called (in that order). POST was inspired from the Design By Contract department, and are meant to execute assertions on the result. If you leave a block through an exception you don't have a result, so I don't think running a POST block makes sense. OK, if POST is only for asserting on the return value that would make sense. But I thought POST was also supposed to be able to assert that global state had been left as it should, in which case it should be run even on exceptional exit? I'm not sure how any given POST block is supposed to distinguish between an ordinary undef return and an exception, though, to avoid checking the return value. Some sort of guarantee that $! is undef in a POST block unless an exception is currently being thrown might be helpful, but I'm not sure how that interacts with the Perl 6 exception model as a whole. I'm not sure about running LEAVE blocks either, because that's what CATCH blocks are for. LEAVE blocks I am certain *should* be run, no matter how the block is exitted (well, unless a PRE fails: see below). They are equivalent to 'finally' blocks in other languages, and AIUI they are for cleanup: closing files, tearing down database connections and the like. What if a PRE block fails: is the POST queue on the same block called? (Do you have to satisfy your post-conditions even if your pre-conditions failed?) I'd say that if a PRE block fails, nothing else is run (neither LEAVE nor POST nor ...) I agree that none of ENTER, LEAVE or the main body of the block should be run. However, if a POST block is asserting, say, that a global holds a valid value, shouldn't that still be checked even if your preconditions failed? I admit I haven't read much about DBC. - If a POST block is called as a result of a thrown exception, and it fails, which exception 'wins'? Question obsoleted by previous answer ;-) ...maybe :). - Can a try block catch an exception thrown from its own ENTER or LEAVE queue? Yes. OK. What about PRE/POST? It seems wrong somehow to be able to catch failure of your own pre-/post-conditions: they are meant for the caller to catch. Does that seem right? Ben
confusing list assignment tests
I'm in the mood to question my sanity, so I'm seeking feedback for some test mangling: In t/spec/S03-operators/assign.t there are some tests that cause me a headache. I'm trying to re-write them to not use the now-gone want() function, but I'd have to understand them first ;-) A good example is this one: sub W () { substr(eval('want'), 0, 1) } ... # line 560: { my @a; my @z = (@a[0] = W, W); #?rakudo 2 todo 'want function' is(@a, 'L','lhs treats @a[0] as list'); is(@z[0], 'L', 'lhs treats @a[0] as list'); ok(!defined(@z[1]), 'lhs treats @a[0] as list'); } This tests that 1) both calls to want() are in list context 2) @a[0] gets only the return value of the first call to W() 3) @z[0] gets the same thing 4) There's no item for @z[1] Somehow I think this test (and many similar tests) are dead wrong. Here's why: Either it's parsed as '@a[0] = (W, W)' (list assignment), then @a should get both elements, and so should @z. Or it's parsed as '(@a[0] = W), W' (item assignment), then the first call should be in item context, and the second one in list context, and @z should still get both items. Right? Or am I completely missing something important here? My current plan is to write such tests as sub l { 1, 2 } # return a short list { my @a; my @z = (@a[0] = l(), l()); is @a[0].elems, 4, '@a[0] = treats LHS as list' is @z.elems,4, '... and passes all elements on the right'; } Does this look sane, and match your understanding of assignment? Cheers, Moritz
r27784 - docs/Perl6/Spec
Author: pmichaud Date: 2009-07-28 21:45:55 +0200 (Tue, 28 Jul 2009) New Revision: 27784 Modified: docs/Perl6/Spec/S04-control.pod Log: Fix incorrect specification of implicit $_ in blocks. Modified: docs/Perl6/Spec/S04-control.pod === --- docs/Perl6/Spec/S04-control.pod 2009-07-28 19:37:57 UTC (rev 27783) +++ docs/Perl6/Spec/S04-control.pod 2009-07-28 19:45:55 UTC (rev 27784) @@ -44,7 +44,7 @@ (either explicitly or implicitly) is treated as though C<$_> were a formal parameter: -$func = { .print if $_ }; # Same as: $func = -> $_ { .print if $_ }; +$func = { .print if $_ }; # Same as: $func = <-> $_ { .print if $_ }; $func("printme"); In any case, all formal parameters are the equivalent of C variables
Re: confusing list assignment tests
On Tue, Jul 28, 2009 at 09:24:40PM +0200, Moritz Lenz wrote: : sub W () { substr(eval('want'), 0, 1) } : ... : : # line 560: : { : my @a; : my @z = (@a[0] = W, W); : #?rakudo 2 todo 'want function' : is(@a, 'L','lhs treats @a[0] as list'); : is(@z[0], 'L', 'lhs treats @a[0] as list'); : ok(!defined(@z[1]), 'lhs treats @a[0] as list'); : } : : : This tests that : 1) both calls to want() are in list context : 2) @a[0] gets only the return value of the first call to W() : 3) @z[0] gets the same thing : 4) There's no item for @z[1] : : Somehow I think this test (and many similar tests) are dead wrong. : Here's why: : : Either it's parsed as '@a[0] = (W, W)' (list assignment), then @a should : get both elements, and so should @z. Not according to S03, at least by one reading. @a[0] as a scalar container only wants one item, so it only takes the first item off the list, and the list assignment produces a warning on the second because it's discarded. Since an assignment returns its left side, only one element is available to @z from @a[0]. : Or it's parsed as '(@a[0] = W), W' (item assignment), then the first : call should be in item context, and the second one in list context, and : @z should still get both items. It's not parsed like that, because only $x, $$xref, $($xref) and such are allowed targets for item assignment. Basically, it has to start with a $ sigil and not do anything fancy like subscripting. However, if you say @z = $x = $a, $b; it parses as @z = ($x = $a), $b and $b ends up in @z[1] but not in $x, which only gets $a. : Right? Or am I completely missing something important here? To get all the elements into $x you'd have to say @z = $x = ($a, $b); and @z[0] would be ($a,$b) with some type or other, whatever was returned by the parens, quite possibly Parcel (that is, List of Thunk or some such). : My current plan is to write such tests as : : sub l { 1, 2 } # return a short list : { : my @a; : my @z = (@a[0] = l(), l()); : is @a[0].elems, 4, '@a[0] = treats LHS as list' : is @z.elems,4, '... and passes all elements on the right'; : } : : Does this look sane, and match your understanding of assignment? Yes, but no. @z.elems and @a[0].elems should both be 1, I suspect. I wish we had a way of trapping and testing warnings too so we could see that 3 elements were discarded by the inner list assignment.. Larry
Re: confusing list assignment tests
Larry Wall wrote: > Moritz Lenz wrote: > : Either it's parsed as '@a[0] = (W, W)' (list assignment), then @a should > : get both elements, and so should @z. > > Not according to S03, at least by one reading. �...@a[0] as a scalar > container only wants one item, so it only takes the first item off > the list, and the list assignment produces a warning on the second > because it's discarded. Since an assignment returns its left side, > only one element is available to @z from @a[0]. So, do we still have p5's 'want_array' (or whatever it was called)? That is, the predicate that tells the you whether the function is being called in item or list context? I know that the generalized 'want' function proved to be unworkable; but I'd expect p6 to at least be able to do everything that p5 can do; and that includes functions that are aware of whether they're being used as singular or plural. -- Jonathan "Dataweaver" Lang
Re: confusing list assignment tests
Thanks for the quick reply. Larry Wall wrote: > On Tue, Jul 28, 2009 at 09:24:40PM +0200, Moritz Lenz wrote: > : sub W () { substr(eval('want'), 0, 1) } > : ... > : > : # line 560: > : { > : my @a; > : my @z = (@a[0] = W, W); > : #?rakudo 2 todo 'want function' > : is(@a, 'L','lhs treats @a[0] as list'); > : is(@z[0], 'L', 'lhs treats @a[0] as list'); > : ok(!defined(@z[1]), 'lhs treats @a[0] as list'); > : } > : > : > : This tests that > : 1) both calls to want() are in list context > : 2) @a[0] gets only the return value of the first call to W() > : 3) @z[0] gets the same thing > : 4) There's no item for @z[1] > : > : Somehow I think this test (and many similar tests) are dead wrong. > : Here's why: > : > : Either it's parsed as '@a[0] = (W, W)' (list assignment), then @a should > : get both elements, and so should @z. > > Not according to S03, at least by one reading. @a[0] as a scalar > container only wants one item, so it only takes the first item off > the list, and the list assignment produces a warning on the second > because it's discarded. Since an assignment returns its left side, > only one element is available to @z from @a[0]. So it's parsed like a list assignment, but list-assigning to a scalar container doesn't promote the whole RHS to a Capture (or whatever it ends up being) as it would do in the case of item assignment, but takes one item off. OK. I guess when I initialize @a[0] = [] it's the same, because then @a[0] is still a scalar, right? Only when I wrote @a[0] := [] I'd get all items in @a[0]. > : Or it's parsed as '(@a[0] = W), W' (item assignment), then the first > : call should be in item context, and the second one in list context, and > : @z should still get both items. > > It's not parsed like that, because only $x, $$xref, $($xref) and such > are allowed targets for item assignment. Basically, it has to start > with a $ sigil and not do anything fancy like subscripting. However, > if you say > > @z = $x = $a, $b; > > it parses as @z = ($x = $a), $b and $b ends up in @z[1] but not > in $x, which only gets $a. > > : Right? Or am I completely missing something important here? > > To get all the elements into $x you'd have to say > > @z = $x = ($a, $b); > > and @z[0] would be ($a,$b) with some type or other, whatever was > returned by the parens, quite possibly Parcel (that is, List of Thunk > or some such). Ok, that makes sense to me. > : My current plan is to write such tests as > : > : sub l { 1, 2 } # return a short list > : { > : my @a; > : my @z = (@a[0] = l(), l()); > : is @a[0].elems, 4, '@a[0] = treats LHS as list' > : is @z.elems,4, '... and passes all elements on the right'; > : } > : > : Does this look sane, and match your understanding of assignment? > > Yes, but no. @z.elems and @a[0].elems should both be 1, I suspect. > I wish we had a way of trapping and testing warnings too so we could > see that 3 elements were discarded by the inner list assignment.. > > Larry Cheers, Moritz
Re: confusing list assignment tests
My understanding is that the P6 way to do that is to return a Capture containing the desired return values (which can lazily do things only when accessed) in the appropriate slots. On 7/28/09, Jon Lang wrote: > Larry Wall wrote: >> Moritz Lenz wrote: >> : Either it's parsed as '@a[0] = (W, W)' (list assignment), then @a should >> : get both elements, and so should @z. >> >> Not according to S03, at least by one reading. �...@a[0] as a scalar >> container only wants one item, so it only takes the first item off >> the list, and the list assignment produces a warning on the second >> because it's discarded. Since an assignment returns its left side, >> only one element is available to @z from @a[0]. > > So, do we still have p5's 'want_array' (or whatever it was called)? > That is, the predicate that tells the you whether the function is > being called in item or list context? I know that the generalized > 'want' function proved to be unworkable; but I'd expect p6 to at least > be able to do everything that p5 can do; and that includes functions > that are aware of whether they're being used as singular or plural. > > -- > Jonathan "Dataweaver" Lang > -- Sent from my mobile device Mark J. Reed
Re: confusing list assignment tests
Jon Lang wrote: > Larry Wall wrote: >> Moritz Lenz wrote: >> : Either it's parsed as '@a[0] = (W, W)' (list assignment), then @a should >> : get both elements, and so should @z. >> >> Not according to S03, at least by one reading. @a[0] as a scalar >> container only wants one item, so it only takes the first item off >> the list, and the list assignment produces a warning on the second >> because it's discarded. Since an assignment returns its left side, >> only one element is available to @z from @a[0]. > > So, do we still have p5's 'want_array' (or whatever it was called)? No. > That is, the predicate that tells the you whether the function is > being called in item or list context? I know that the generalized > 'want' function proved to be unworkable; but I'd expect p6 to at least > be able to do everything that p5 can do; and that includes functions > that are aware of whether they're being used as singular or plural. The problem is that it's impossible in Perl 6, because we have multi dispatch. Consider this simple case: multi a(@a*){ } # provides list context onto the arguments multi a(Str $x) { } # provides Str context or at least some sort of # item context on the argument sub b() { } a(b()); # you can't know which context b() is called in since the multi dispatch to a() depends on the return value of b(), we only know b()'s context after we know its return value - which is too late. So the "active" context propagation that Perl 5 does is not possible in Perl 6. Cheers, Moritz
Re: confusing list assignment tests
Mark J. Reed wrote: > My understanding is that the P6 way to do that is to return a Capture > containing the desired return values (which can lazily do things only > when accessed) in the appropriate slots. Return a Capture or a more heavily overloaded object, depending on how fine a degree of context discrimination you need. Further to that idea, I'm actually planning to attempt to port Contextual::Return to Perl 6 in the next few weeks. Damian
Re: confusing list assignment tests
On Tue, Jul 28, 2009 at 01:22:28PM -0700, Jon Lang wrote: : Larry Wall wrote: : > Moritz Lenz wrote: : > : Either it's parsed as '@a[0] = (W, W)' (list assignment), then @a should : > : get both elements, and so should @z. : > : > Not according to S03, at least by one reading. �...@a[0] as a scalar : > container only wants one item, so it only takes the first item off : > the list, and the list assignment produces a warning on the second : > because it's discarded. Since an assignment returns its left side, : > only one element is available to @z from @a[0]. : : So, do we still have p5's 'want_array' (or whatever it was called)? : That is, the predicate that tells the you whether the function is : being called in item or list context? I know that the generalized : 'want' function proved to be unworkable; but I'd expect p6 to at least : be able to do everything that p5 can do; and that includes functions : that are aware of whether they're being used as singular or plural. Perl 6 is not about doing everything that Perl 5 can do. It's about breaking everything that needs breaking. This is one of those things. We *may* have something like want someday, but if so, it can only work by time travel (read: return a type profile with lazy values, and let the eventual binding of the type profile call back for the actual values). But I doubt will require such for 6.0.0 in any case. But Perl 6 is based on knowing the types to do MMD, and we have to know at least those types, even if we don't know the values. That makes it very difficult for a function that wants to return *different* types based on the eventual dispatch, since the eventual dispatch depends on those types in a circular sort of way. Sanity dictates that we make time flow forward rather than backward for most of what Perl 6 programmers will want to do most of the time. Larry
Re: confusing list assignment tests
Damian Conway wrote: > Mark J. Reed wrote: >> My understanding is that the P6 way to do that is to return a Capture >> containing the desired return values (which can lazily do things only >> when accessed) in the appropriate slots. > > Return a Capture or a more heavily overloaded object, depending on how > fine a degree of context discrimination you need. > > Further to that idea, I'm actually planning to attempt to port > Contextual::Return to Perl 6 in the next few weeks. Right. I don't think that a Capture has sufficiently fine context discrimination to handle even those cases that Perl 5 was able to handle. For instance, consider a function that's intended to return a list of items in list context, or a count of the items in item context: since imposing item context on a Capture object extracts the first positional parameter, a Capture object wouldn't be able to be loaded properly to do this. So something along the lines of Contextual::Return is probably a good idea. Hmm... it might be nice to be able to use something akin to a "given ... when" construct: sub foo() { return context { when Item { 5 } when List { a, b, c, d, e } } } The idea here is that the 'context' keyword means that the block is to be called as soon as the desired context is known, with said context being passed to the block as its topic ('$_'). -- Jonathan "Dataweaver" Lang
Re: confusing list assignment tests
On Tue, Jul 28, 2009 at 10:42:01PM +0200, Moritz Lenz wrote: : I guess when I initialize @a[0] = [] it's the same, because then @a[0] : is still a scalar, right? No, as in Perl 5 [] still produces a scalar object that hides the arrayness from list context, so it's like: $b = []; @a[0] = $b; It doesn't unwrap the scalar object to see what's in it. : Only when I wrote @a[0] := [] I'd get all items in @a[0]. That binds the Array in place of the current @a[0] container, just as $b = []; @a[0] := $b; would. Just as $obj and @$obj default differently in list context, so do [] and (). To put it another way, Array and Hash objects don't naturally interpolate into list context without some help from @ or % syntax (or equivalent method call). If I say: @a = 42, [1,2,3], { foo => 1, bar => 2, baz => 3 }; then @a will always end up with exactly 3 elements, just as if I'd said: $a = 42; $b = [1,2,3]; $c = { foo => 1, bar => 2, baz => 3 }; @a = $a, $b, $c; Larry