[perl6/specs] 216855: [S04] Add missing parenthesis in zip() example
Branch: refs/heads/master Home: https://github.com/perl6/specs Commit: 2168554941a2c85b7c3a1512382a965aa3139258 https://github.com/perl6/specs/commit/2168554941a2c85b7c3a1512382a965aa3139258 Author: Sterling Hanenkamp Date: 2016-01-16 (Sat, 16 Jan 2016) Changed paths: M S04-control.pod Log Message: --- [S04] Add missing parenthesis in zip() example Commit: 21525aab69789f0d7a00640d75ae332d4fad9e73 https://github.com/perl6/specs/commit/21525aab69789f0d7a00640d75ae332d4fad9e73 Author: niner Date: 2016-01-17 (Sun, 17 Jan 2016) Changed paths: M S04-control.pod Log Message: --- Merge pull request #105 from zostay/zip-parens [S04] Add missing parenthesis in zip() example Compare: https://github.com/perl6/specs/compare/b0657be1c92e...21525aab6978
[perl6/specs] 3f0277: S04: Fix pre-GLR-ism
Branch: refs/heads/master Home: https://github.com/perl6/specs Commit: 3f0277cff77649169b8854470c13220f16b8db57 https://github.com/perl6/specs/commit/3f0277cff77649169b8854470c13220f16b8db57 Author: Moritz Lenz Date: 2015-09-19 (Sat, 19 Sep 2015) Changed paths: M S04-control.pod Log Message: --- S04: Fix pre-GLR-ism isn't it wonderful how much simpler this passage becomes through the GLR?
[perl6/specs] 558155: De-Parcel-ify S04
Branch: refs/heads/master Home: https://github.com/perl6/specs Commit: 558155b811176632b4e00366df2d40c5eeb89cfc https://github.com/perl6/specs/commit/558155b811176632b4e00366df2d40c5eeb89cfc Author: Moritz Lenz Date: 2015-09-05 (Sat, 05 Sep 2015) Changed paths: M S04-control.pod Log Message: --- De-Parcel-ify S04
[perl6/specs] 3be145: Revert addition of 'slip' to S04
Branch: refs/heads/master Home: https://github.com/perl6/specs Commit: 3be145ca3e36f03fa3832cd25c939fc315472fdf https://github.com/perl6/specs/commit/3be145ca3e36f03fa3832cd25c939fc315472fdf Author: Carl Masak Date: 2014-10-24 (Fri, 24 Oct 2014) Changed paths: M S04-control.pod Log Message: --- Revert addition of 'slip' to S04 'slip' may (or may not) be a nice+useful feature, but we're not ready to add it to core just now. In GLR we have more pressing concerns. This reverts commit 24850d6b665913be797067a5c80e8d3fdfc03c1b. This reverts commit e4c5b10b3bed23d270f50208b9e4c621c18dacba.
[perl6/specs] 12b6d9: typo in S04
Branch: refs/heads/master Home: https://github.com/perl6/specs Commit: 12b6d9f6ea29b46898272d024de5cb81b5d8649d https://github.com/perl6/specs/commit/12b6d9f6ea29b46898272d024de5cb81b5d8649d Author: diakopter Date: 2013-02-26 (Tue, 26 Feb 2013) Changed paths: M S04-control.pod Log Message: --- typo in S04
[perl6/specs] 8c3efe: [S04] small nit
Branch: refs/heads/master Home: https://github.com/perl6/specs Commit: 8c3efe4bf60065452c453cae3e7d4187e750d1be https://github.com/perl6/specs/commit/8c3efe4bf60065452c453cae3e7d4187e750d1be Author: Moritz Lenz Date: 2012-05-27 (Sun, 27 May 2012) Changed paths: M S04-control.pod Log Message: --- [S04] small nit let and temp are prefix operators, not ordinary functions
[perl6/specs] 536a48: [S04] note one more that &eval does not catch exce...
Branch: refs/heads/master Home: https://github.com/perl6/specs Commit: 536a4833099b1313d14705df5fb10ee073b3a5e5 https://github.com/perl6/specs/commit/536a4833099b1313d14705df5fb10ee073b3a5e5 Author: Moritz Lenz Date: 2012-04-09 (Mon, 09 Apr 2012) Changed paths: M S04-control.pod Log Message: --- [S04] note one more that &eval does not catch exceptions
[perl6/specs] 937f37: [S04] unspec submethod PRE/POST
Branch: refs/heads/master Home: https://github.com/perl6/specs Commit: 937f37f7e03a53a6ee167556ab7ab4f0d14c43ae https://github.com/perl6/specs/commit/937f37f7e03a53a6ee167556ab7ab4f0d14c43ae Author: Carl Masak Date: 2012-03-11 (Sun, 11 Mar 2012) Changed paths: M S04-control.pod Log Message: --- [S04] unspec submethod PRE/POST See <http://irclog.perlgeek.de/perl6/2012-03-11#i_5275742> for the discussion that precipitated their removal. Anyone with a working implementation of them is free to add them back. :-)
[perl6/specs] 578e3c: [S04] un-spec method-level PRE/POST
Branch: refs/heads/master Home: https://github.com/perl6/specs Commit: 578e3cbf3189098e7e854d6222905218d7e67ebc https://github.com/perl6/specs/commit/578e3cbf3189098e7e854d6222905218d7e67ebc Author: Carl Masak Date: 2012-03-11 (Sun, 11 Mar 2012) Changed paths: M S04-control.pod Log Message: --- [S04] un-spec method-level PRE/POST The intent was to extend block-level PRE/POST to something that could do Eiffel-style Design-by-Contract assertions. This is an intriguing idea, but not in the way the spec outlined it. See <http://www.nntp.perl.org/group/perl.perl6.language/2012/03/msg34803.html> for details.
[perl6/specs] 6828ff: Fix self-contradiction in S04
Branch: refs/heads/master Home: https://github.com/perl6/specs Commit: 6828ff448731bb0c5327f6202159e4b1a448654e https://github.com/perl6/specs/commit/6828ff448731bb0c5327f6202159e4b1a448654e Author: Stefan O'Rear Date: 2011-03-05 (Sat, 05 Mar 2011) Changed paths: M S04-control.pod Log Message: --- Fix self-contradiction in S04
[perl6/specs] a826b5: [S04,S32] implicit loops expect to be controlled b...
Branch: refs/heads/master Home: http://github.com/perl6/specs Commit: a826b588b613ef61471e4d89c6b86d7f3502dcdb http://github.com/perl6/specs/commit/a826b588b613ef61471e4d89c6b86d7f3502dcdb Author: TimToady Date: 2010-09-06 (Mon, 06 Sep 2010) Changed paths: M S04-control.pod M S32-setting-library/Containers.pod Log Message: --- [S04,S32] implicit loops expect to be controlled by bare next and last
r31691 -[S04] more bombastic utterances about not dropping pending exceptions
Author: lwall Date: 2010-07-15 01:53:05 +0200 (Thu, 15 Jul 2010) New Revision: 31691 Modified: docs/Perl6/Spec/S04-control.pod Log: [S04] more bombastic utterances about not dropping pending exceptions Modified: docs/Perl6/Spec/S04-control.pod === --- docs/Perl6/Spec/S04-control.pod 2010-07-14 23:32:07 UTC (rev 31690) +++ docs/Perl6/Spec/S04-control.pod 2010-07-14 23:53:05 UTC (rev 31691) @@ -1043,6 +1043,16 @@ never attempts to handle any exception thrown within its own dynamic scope. (Otherwise any C would cause an infinite loop.) +Any attempt to throw a fatal exception past an already active exception +handler must guarantee to steal the existing fatal exception (plus +any pending exceptions it contains) and add all those to the new +exception's pending list. (This does not apply to control exceptions +described in the next section.) When the new exception is handled, +it must also deal with the list of pending exceptions, or the C +mentioned above will throw a "Pending exceptions not handled" at that point. +Even this does not discard the pending exceptions, so in the final outermost +message, all non-handled exceptions are guaranteed to be listed. + =head1 Control Exceptions All abnormal control flow is, in the general case, handled by the
r31690 -[S04] revise catcher semantics semantics to allow $!.handled = 1 to work as well as case match
Author: lwall Date: 2010-07-15 01:32:07 +0200 (Thu, 15 Jul 2010) New Revision: 31690 Modified: docs/Perl6/Spec/S04-control.pod Log: [S04] revise catcher semantics semantics to allow $!.handled = 1 to work as well as case match Modified: docs/Perl6/Spec/S04-control.pod === --- docs/Perl6/Spec/S04-control.pod 2010-07-14 21:18:42 UTC (rev 31689) +++ docs/Perl6/Spec/S04-control.pod 2010-07-14 23:32:07 UTC (rev 31690) @@ -13,8 +13,8 @@ Created: 19 Aug 2004 -Last Modified: 12 Jul 2010 -Version: 101 +Last Modified: 14 Jul 2010 +Version: 102 This document summarizes Apocalypse 4, which covers the block and statement syntax of Perl. @@ -993,18 +993,46 @@ default {...} } -you're really getting something more like: +you're really calling into a I that looks like: -CATCH { -when Mumble {...} -default {...} +-> $! { +my $SUCCEEDED = 1; # assume we will handle it -leave(Failure); +given $! { +when Mumble {...} +default {...} +$SUCCEEDED = 0;# unassume we handled it +} -KEEP (die("Pending exceptions not handled in $!") unless all($!.pending».handled); $!.handled = 1); -UNDO die $!; +# the user may handle exception either by +# 1. pattern matching in the given +# 2. explicitly setting $!.handled = 1 +$!.handled = 1 if $SUCCEEDED; + +# conjecture: this might be enforced by the exception thrower instead +if $!.handled { +$!.wrap-die("Pending exceptions not handled") unless all($!.pending».handled); +} + +$!; } +The exception thrower looks up the call stack for a catch lambda +that returns the exception object as handled, and then it is happy, +and unwinds the stack to that point. If the exception is returned +as not handled. the exception thrower keeps looking for a higher +dynamic scope for a spot to unwind to. Note that any C in the +catch lambda rethrows outside the lambda as a new exception, wrapping +up the old exception in its new pending list. In this case the lambda +never finishes executing. Resumable exceptions may or may not leave +normally depending on the implementation. If continuations are used, +the C<$!.resume> call will simply goto the continuation in question, +and the lambda's callframe is abandoned. Resumable exceptions may also +be implemented by simply marking the C<$!> exception as "resumed", +in which case the original exception thrower simply returns to +the code that threw the resumable exception, rather than unwinding +before returning. + A C block sees the lexical scope in which it was defined, but its caller is the dynamic location that threw the exception. That is, the stack is not unwound until some exception handler chooses to @@ -1013,7 +1041,7 @@ C block to catch its own exception recursively forever. However, a C must not behave that way, so we say that a C block never attempts to handle any exception thrown within its own dynamic scope. -(Otherwise the C in the previous paragraph would never work.) +(Otherwise any C would cause an infinite loop.) =head1 Control Exceptions @@ -1132,7 +1160,11 @@ that the semantics would be preserved by merely printing out the error and going on. Since all exception handlers run in the dynamic scope of the throw, that reduces to simply returning from the C -function most of the time. +function most of the time. See previous section for discussion of +ways to return from catch lambdas. The control lambda is logically +separate from the catch lambda, though an implementation is allowed +to combine them if it is careful to retain separate semantics for +catch and control exceptions. =head1 The goto statement X
r31645 -[S04] try to nail down CATCH exit semantics a bit more water-tightly
Author: lwall Date: 2010-07-12 21:52:08 +0200 (Mon, 12 Jul 2010) New Revision: 31645 Modified: docs/Perl6/Spec/S04-control.pod Log: [S04] try to nail down CATCH exit semantics a bit more water-tightly Modified: docs/Perl6/Spec/S04-control.pod === --- docs/Perl6/Spec/S04-control.pod 2010-07-12 17:51:44 UTC (rev 31644) +++ docs/Perl6/Spec/S04-control.pod 2010-07-12 19:52:08 UTC (rev 31645) @@ -13,8 +13,8 @@ Created: 19 Aug 2004 -Last Modified: 9 Jul 2010 -Version: 100 +Last Modified: 12 Jul 2010 +Version: 101 This document summarizes Apocalypse 4, which covers the block and statement syntax of Perl. @@ -986,6 +986,25 @@ it treats code inside a C block differently from code that's after all the C blocks but not in a C block. +More specifically, when you write: + +CATCH { +when Mumble {...} +default {...} +} + +you're really getting something more like: + +CATCH { +when Mumble {...} +default {...} + +leave(Failure); + +KEEP (die("Pending exceptions not handled in $!") unless all($!.pending».handled); $!.handled = 1); +UNDO die $!; +} + A C block sees the lexical scope in which it was defined, but its caller is the dynamic location that threw the exception. That is, the stack is not unwound until some exception handler chooses to
r31610 -[S04] emphasize that LEAVE blocks *always* run even under stack unwinding
Author: lwall Date: 2010-07-10 00:59:12 +0200 (Sat, 10 Jul 2010) New Revision: 31610 Modified: docs/Perl6/Spec/S04-control.pod Log: [S04] emphasize that LEAVE blocks *always* run even under stack unwinding Modified: docs/Perl6/Spec/S04-control.pod === --- docs/Perl6/Spec/S04-control.pod 2010-07-09 22:55:41 UTC (rev 31609) +++ docs/Perl6/Spec/S04-control.pod 2010-07-09 22:59:12 UTC (rev 31610) @@ -1230,7 +1230,7 @@ START {...}* on first ever execution, once per closure clone ENTER {...}* at every block entry time, repeats on loop blocks. - LEAVE {...} at every block exit time + LEAVE {...} at every block exit time (even stack unwinds from exceptions) KEEP {...} at every successful block exit, part of LEAVE queue UNDO {...} at every unsuccessful block exit, part of LEAVE queue
r31601 -[S04] simplify definition of successful return to be context agnostic
Author: lwall Date: 2010-07-09 23:10:45 +0200 (Fri, 09 Jul 2010) New Revision: 31601 Modified: docs/Perl6/Spec/S04-control.pod Log: [S04] simplify definition of successful return to be context agnostic define class-level PRE/POST to be submethods that are called like BUILD/DESTROY Modified: docs/Perl6/Spec/S04-control.pod === --- docs/Perl6/Spec/S04-control.pod 2010-07-09 19:47:34 UTC (rev 31600) +++ docs/Perl6/Spec/S04-control.pod 2010-07-09 21:10:45 UTC (rev 31601) @@ -13,8 +13,8 @@ Created: 19 Aug 2004 -Last Modified: 27 Apr 2010 -Version: 98 +Last Modified: 9 Jul 2010 +Version: 99 This document summarizes Apocalypse 4, which covers the block and statement syntax of Perl. @@ -1342,7 +1342,8 @@ their side effects. C and C must return boolean values that are evaluated according to the usual Design by Contract (DBC) rules. (Plus, if you use C/C in a class block, they only execute when the -class block is executed, but C/C in a class block are evaluated +class block is executed, but you may declare C/C submethods +in a class block that will be evaluated around every method in the class.) C and C are just variants of C, and for execution order are treated as part of the queue of C phasers. @@ -1376,8 +1377,19 @@ everything else, to guarantee that even C phasers can't violate DBC. Likewise C phasers fire off before any C or C (though not before C, C, or C, since those are done at compile or -process initialization time). +process initialization time). Much like C and C are implicitly +called in the correct order by C and C, the C/C +calls are via an implicit C method that runs +outside the actual call to the method in question. Class-level C/C +submethods are notionally outside of the method-level C/C blocks. +At each submethod level, C calls (in the normal course of things): +1. class's C submethod +2. method's C phaser +3. method call +4. method's C phaser +5. class's C submethod + If exit phasers are running as a result of a stack unwind initiated by an exception, C<$!> contains the exception that caused it, though it will be marked as handled by then. In any case, the information @@ -1404,11 +1416,15 @@ world in raw form, so that the phaser doesn't accidentally impose context prematurely.) -The topic of the outer block is still available as C<< OUTER::<$_> >>. +The topic of the outer block of a phaser is still available as C<< OUTER::<$_> >>. Whether the return value is modifiable may be a policy of the phaser in question. In particular, the return value should not be modified within a C phaser, but a C phaser could be more liberal. +Class-level C and C submethods are not in the lexical +scope of a method, and are not run in the dynamic scope of the method, +so cannot see the method's C<$_> at all. + =head1 Statement parsing In this statement: @@ -1578,14 +1594,7 @@ is okay. In the absence of error exception propagation, a successful exit is one that -returns a defined value in item context, or any number of values -in list context as long as the length is defined. (A length of +Inf -is considered a defined length. A length of 0 is also a defined length, -which means it's a "successful" return even though the list would evaluate -to false in a boolean context.) A list can have a defined length -even if it contains undefined scalar values. A list is of undefined -length only if it contains an undefined generator, which, happily, is -what is returned by the C function when used in list context. +returns a defined value or parcel. (A defined parcel may contain undefined values.) So any Perl 6 function can say fail "message";
r31532 -[S04] Clarify interaction of lexical classes and packages with members after discussion with TimToady
Author: sorear Date: 2010-07-03 06:39:32 +0200 (Sat, 03 Jul 2010) New Revision: 31532 Modified: docs/Perl6/Spec/S04-control.pod Log: [S04] Clarify interaction of lexical classes and packages with members after discussion with TimToady Modified: docs/Perl6/Spec/S04-control.pod === --- docs/Perl6/Spec/S04-control.pod 2010-07-02 23:37:35 UTC (rev 31531) +++ docs/Perl6/Spec/S04-control.pod 2010-07-03 04:39:32 UTC (rev 31532) @@ -1625,7 +1625,7 @@ no guarantee can be made that the scope needed for cloning will remain in existence over the life of the reference.) -In particular, named subroutines are a special problem when embedded in +In particular, package subroutines are a special problem when embedded in a changing lexical scope (when they make reference to it). The binding of such a definition to a name within a symbol table counts as taking a reference, so at compile time there is an initial binding @@ -1642,6 +1642,21 @@ take into consideration that it is functioning only as a cache of the most recent cloning, not as a surrogate for the current lexical scope.) +Matters are more complicated if the package in question is lexically defined. +In such cases, the package must be cloned as if it were a sub on entry to the +corresponding lexical scope. All runtime instances of a single package +declaration share the same set of compile-time declared functions, however, +the runtime instances can have different lexical environments as described in +the preceding paragraph. If multiple conflicting definitons of a sub exist +for the same compile-time package, an error condition exists and behavior is +not specified for Perl 6.0. + +Methods in classes behave functionally like package subroutines, and have the +same binding behavior if the classes are cloned. Note that a class declaration, +even an augment, is fundamentally a compile-time operation; composition only +happens once and the results are recorded in the prototype class. Runtime +typological manipulations are limited to reseating C scopes of methods. + Lexical names do not share this problem, since the symbol goes out of scope synchronously with its usage. Unlike global subs, they do not need a compile-time binding, but like global subs,
Re: Clarification of S04 closure traits
Sorry for the delay in replying, but I was busy with other things and I wanted to give other people a chance to reply. Since noone has, might it be possible to get the attached patches committed? I'm not familiar with the protocol for such things so, again, I'm sorry if I've got it wrong. Ben --- S04-control.pod.orig 2009-08-11 08:43:36.00000 +0100 +++ S04-control.pod 2009-08-11 09:03:42.0 +0100 @@ -1232,6 +1232,21 @@ before C, C, or C, since those are done at compile or process initialization time). +If an exception is thrown through a block without a C block, the +C, C and C blocks will be run at that point, with +C<$!> set to the in-flight exception. If there is no in-flight +exception when these blocks are run, C<$!> will be C. The last +exception caught in the outer block is available as C<< OUTER::<$!> >>, +as usual. + +An exception thrown from an C block will abort the C +queue, but one thrown from a C block will not. The exceptions +thrown by failing C and C blocks cannot be caught by a +C in the same block, which implies that C blocks are not +run if a C block fails. If a C fails while an exception is in +flight the C failure doesn't replace C<$!> but goes straight into +C<$!.pending>. + For blocks such as C and C that are run when exiting a scope normally, the return value (if any) from that scope is available as the current topic. (It is presented as a C object.) Index: S04-closure-traits/enter-leave.t =========== --- S04-closure-traits/enter-leave.t (revision 27955) +++ S04-closure-traits/enter-leave.t (working copy) @@ -2,7 +2,7 @@ use Test; -plan 11; +plan 19; # L # L @@ -92,4 +92,92 @@ }), 1, 'leave triggers LEAVE {}'; } +{ +my $str; +try { +ENTER { $str ~= '(' } +LEAVE { $str ~= ')' } +$str ~= 'x'; +die 'foo'; +} +is $str, '(x)', 'die calls LEAVE blocks'; +} + +{ +my $str; +try { +LEAVE { $str ~= $! // '' } +die 'foo'; +} +is $str, 'foo', '$! set in LEAVE if exception thrown'; +} + +{ +my $str; +{ +LEAVE { $str ~= (defined $! ? 'yes' : 'no') } +try { die 'foo' } +$str ~= (defined $! ? 'aye' : 'nay'); +} +is $str, 'ayeno', '$! not set in LEAVE if exception not thrown'; +} + +{ +my $str; +try { +$str ~= '('; +try { +ENTER { die 'foo' } +$str ~= 'x'; +} +$str ~= ')'; +} +is $str, '()', 'die in ENTER caught by try'; +} + +{ +my $str; +try { +$str ~= '('; +try { +LEAVE { die 'foo' } +$str ~= 'x'; +} +$str ~= ')'; +} +is $str, '(x)', 'die in LEAVE caught by try'; +} + +{ +my $str; +try { +$str ~= '('; +try { +ENTER { $str ~= '['; die 'foo' } +LEAVE { $str ~= ']' } +$str ~= 'x'; +} +$str ~= ')'; +} +is $str, '([])', 'die in ENTER calls LEAVE'; +} + +{ +my $str; +try { +ENTER { $str ~= '1'; die 'foo' } +ENTER { $str ~= '2' } +} +is $str, '1', 'die aborts ENTER queue'; +} + +{ +my $str; +try { +LEAVE { $str ~= '1' } +LEAVE { $str ~= '2'; die 'foo' } +} +is $str, '21', 'die doesn\'t abort LEAVE queue'; +} + # vim: ft=perl6 Index: S04-closure-traits/pre-post.t === --- S04-closure-traits/pre-post.t (revision 27955) +++ S04-closure-traits/pre-post.t (working copy) @@ -9,7 +9,7 @@ # TODO: # * Multiple inheritance + PRE/POST blocks -plan 18; +plan 25; sub foo(Num $i) { PRE { @@ -125,4 +125,82 @@ lives_ok { $pt.test(2) }, 'POST receives return value as $_ (succeess)'; dies_ok { $pt.test(1) }, 'POST receives return value as $_ (failure)'; +{ +my $str; +{ +PRE { $str ~= '('; 1 } +POST { $str ~= ')'; 1 } +$str ~= 'x'; +} +is $str, '(x)', 'PRE and POST run on ordinary blocks'; +} + +{ +my $str; +{ +POST { $str ~= ')'; 1 } +LEAVE { $str ~= ']' } +ENTER { $str ~= '[' } +PRE { $str ~= '('; 1 } +$str ~= 'x'; +} +is $str, '([x])', 'PRE/POST run outside ENTER/LEAV
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
Re: Clarification of S04 closure traits
Ben Morrow wrote: > 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 never thought of that, because in the only other DBC-enabled language that I've used (Eiffel) there are other assertions types for that (iirc they are called "class invariants", but I'm not entirely sure) which are run after every method call from the outside of the class, or something along these lines. I haven't seen such a thing in the spec in Perl 6, so either we invent such a thing, or pick up your position (always run POST) > 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. Same here. >> 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. You're right here; it's the KEEP block that is only executed on normal exit. >>> 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. Same as for the first question. >>> - 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 :). If not: $! is an aggregate of all exceptions thrown so far, so whichever way we go, we don't lose any information. I fear that doesn't help you very much, though, because it's different in Perl 5. I personally prefer to know about the first exception, for example I find it more informative that an open() fails than that a subsequent print() to that file failed. >>> - 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? Yes. (Actually they are not really meant to be caught, because they always reveal programming errors, but I guess sometimes you still can't avoid it). I just fear that I haven't contributed much clarity at all :/ Cheers, Moritz
Re: Clarification of S04 closure traits
Ben Morrow wrote: > I'm iworking on a patch for Perl 5 that implements the Perl 6 closure > traits (ENTER/LEAVE/...) as special blocks. There are several details > that aren't clear to me from either S04 or the spec tests; I apologize > if these have been discussed before, as I haven't been following p6l. No need to apologize; such things should be clear from reading the spec. Note that my answers are in no way authoritative, just proposals on how to handle it (and maybe starting point of useful discussions). > I'm also not subscribed, so if people could keep me in the CC that would > be appreciated. > > - 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. I'm not sure about running LEAVE blocks either, because that's what CATCH blocks are for. > 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 ...) > - If a POST block is called as a result of a thrown exception, and it > fails, which exception 'wins'? Question obsoleted by previous answer ;-) > - Presumably if an ENTER block dies, the rest of that ENTER queue is > abandoned. Does that also apply to the LEAVE queue? What should > > { > LEAVE { say "leave1" } > LEAVE { say "leave2"; die "foo"; } > } > > print? Similarly POST: once one post-condition has failed, are > subsequent post-conditions checked? > - Can a try block catch an exception thrown from its own ENTER or LEAVE > queue? Yes. > For example in this case: > > try { > > try { > ENTER { die "foo" } > CATCH { default { say "caught inside" } } > } > > CATCH { default { say "caught outside" } } > } > > which CATCH block gets the exception? What about PRE/POST: can you > CATCH failure of your own pre-/post-conditions? > > - Does it make any difference in any of the above if 'die' is replaced > by 'exit'? No idea, really. HTH, Moritz
Clarification of S04 closure traits
I'm iworking on a patch for Perl 5 that implements the Perl 6 closure traits (ENTER/LEAVE/...) as special blocks. There are several details that aren't clear to me from either S04 or the spec tests; I apologize if these have been discussed before, as I haven't been following p6l. I'm also not subscribed, so if people could keep me in the CC that would be appreciated. - Presumably when an exception is thrown through a block, the LEAVE and POST queues are called (in that order). 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?) - If a POST block is called as a result of a thrown exception, and it fails, which exception 'wins'? - Presumably if an ENTER block dies, the rest of that ENTER queue is abandoned. Does that also apply to the LEAVE queue? What should { LEAVE { say "leave1" } LEAVE { say "leave2"; die "foo"; } } print? Similarly POST: once one post-condition has failed, are subsequent post-conditions checked? - Can a try block catch an exception thrown from its own ENTER or LEAVE queue? For example in this case: try { try { ENTER { die "foo" } CATCH { default { say "caught inside" } } } CATCH { default { say "caught outside" } } } which CATCH block gets the exception? What about PRE/POST: can you CATCH failure of your own pre-/post-conditions? - Does it make any difference in any of the above if 'die' is replaced by 'exit'? Ben
Re: S04-related closure question
On Sat, Jul 12, 2008 at 09:52:34PM -0500, Patrick R. Michaud wrote: > What would be the expected output from the following? > > my $a = foo(); > my $b; > > { > my $x = 1; > sub get_x() { return $x; } > sub foo() { return &get_x; } > $b = foo(); > } > > my $c = foo(); > > say "a: ", $a(); > say "b: ", $b(); > say "c: ", $c(); If I'm reading the current version of S04 correctly, I'm guessing the above will produce a: Use of undefined value b: 1 c: 1 > As a followup question, what about...? > > my @array; > for 1..3 -> $x { > sub get_x() { return $x; } > push @array, &get_x; > } > > for @array -> $f { say $f(); } This one would output "1\n2\n3\n". Are my interpretations correct here? Pm
Re: Conceptual question on exception in S04
Larry Wall larry-at-wall.org |Perl 6| wrote: No, just the new exception, which merely has to contain the old unhandled exceptions somehow in case the user wants more information. OK, so it's more like the "inner exception" in Microsoft's .NET framework. My C++ exceptions have always had the ability to record multiple "stanzas" of information, to re-throw and update the picky details with context-specific interpretation. It sounds like what you want is that if there is a pending unhandled exception in dynamic scope, then 'die' or the fresh Exception object's constructor will automatically pick that up as the inner exception. By the way, I'd like to see a user interface where the outer exception is the one printed out in simple form, with the complete "cockpit recorder" dump of information going into a file that is browser accessible with a click on a link in the error message to "more info". Larry I did that about fifteen years ago. The dialog box had a drop-down to show all the layers of information, and also a save button. The format predates XML though, and was designed for high-speed and failsafe logging, so it used control characters instead of XML-like tags. --John
Re: Conceptual question on exception in S04
On Wed, Sep 03, 2008 at 06:44:22PM -0500, John M. Dlugosz wrote: > I'm trying to work out some details of this area, but I don't understand > what S04 is trying to say. Could someone please point me in the right > direction? I'd be happy to then edit the S04 to contribute. > > > In S04, the "Exceptions" section mentions that $! contains multiple > exceptions. > So what type is it? Why isn't it @! ? I says that they are thrown as a > single new exception. So what type is that new exception? A multi-exception > of > some kind? No, just the new exception, which merely has to contain the old unhandled exceptions somehow in case the user wants more information. > How do you get multiple pending exceptions in the first place? > > If you mean that exceptions can be thrown (and handled) within the handling of > another exception, then the list should be more of a stack. Should the > handler > then see the topmost one as its topic? If you really did make the whole list > the topic then it would be difficult to match. All I care is that we don't discard useful information here. Only the outermost exception needs to be directly matchable against via $!. > How would you access the other exceptions in $!, presumably testing them for > .defined etc.? I would assume that the $! object can be accessed as an array in that case, unless someone can argue for a different interface. By the way, I'd like to see a user interface where the outer exception is the one printed out in simple form, with the complete "cockpit recorder" dump of information going into a file that is browser accessible with a click on a link in the error message to "more info". Larry
Conceptual question on exception in S04
I'm trying to work out some details of this area, but I don't understand what S04 is trying to say. Could someone please point me in the right direction? I'd be happy to then edit the S04 to contribute. In S04, the "Exceptions" section mentions that $! contains multiple exceptions. So what type is it? Why isn't it @! ? I says that they are thrown as a single new exception. So what type is that new exception? A multi-exception of some kind? How do you get multiple pending exceptions in the first place? If you mean that exceptions can be thrown (and handled) within the handling of another exception, then the list should be more of a stack. Should the handler then see the topmost one as its topic? If you really did make the whole list the topic then it would be difficult to match. How would you access the other exceptions in $!, presumably testing them for .defined etc.? Granted that the paragraph is muddled due to old edits from previous ideas, I'd be happy to rewrite it. But what =is= the current central concept that it is trying to explain? --John
S04-related closure question
What would be the expected output from the following? my $a = foo(); my $b; { my $x = 1; sub get_x() { return $x; } sub foo() { return &get_x; } $b = foo(); } my $c = foo(); say "a: ", $a(); say "b: ", $b(); say "c: ", $c(); As a followup question, what about...? my @array; for 1..3 -> $x { sub get_x() { return $x; } push @array, &get_x; } for @array -> $f { say $f(); } Pm
Re: Sequential bias in S04 (and Perl6 in general)
On Fri, 2008-01-11 at 10:34 -0800, Dave Whipp wrote: > Matthew Walton wrote: > > > I wouldn't agree with that at all. I think of arrays as ordered constructs, > > so I'd want the default iteration over my array to happen in the order of > > the indices. > > I guess that depends on whether you think of the array as a list or as a > ram. I know that a group at microsoft added a ParallelArray datatype > (ftp://ftp.research.microsoft.com/pub/tr/TR-2005-184.pdf) to C# as a way > to distinguish the intent (they speed up data-parallel code by compiling > it down to your GPU/graphics card). Perl6, being an operator-oriented > language, associates the distinction with the operators rather than with > the datatype. This is probably a better approach, but it does mean that > you need an operator whenever you want to treat the array as > data-parallel. (BTW, data-parallel arrays differ from bags in that they > have an ordered index that is preserved across unordered operations) Good point, a parallel operation over a list would let you preserve ordering but still benefit from concurrency with operations where iterating in order is irrelevant. Which, come to think of it, covers quite a lot of cases. > Of course, it's not necessarily true that "you know" that something is > safe -- often "you think" it's safe but then you get an intermittent > failure at runtime,. I would love to be able to tell the compiler "I > think this is safe" and have it tell me "you're wrong" as a compile-time > error (this is one of the things that an explicit type system is good > for). But perhaps Perl is too dynamic a language for that. Well, I was thinking with 'knowing' that something was safe that you'd figured out that it was free of side effects by studying the behaviour of everything you use within the relevant routines... ...in the real world, you need the compiler to be able to do some of that for you I guess. And Perl 6's optionally explicit type system might be able to express that sort of thing. signature.asc Description: This is a digitally signed message part
Re: Sequential bias in S04 (and Perl6 in general)
Matthew Walton wrote: I wouldn't agree with that at all. I think of arrays as ordered constructs, so I'd want the default iteration over my array to happen in the order of the indices. I guess that depends on whether you think of the array as a list or as a ram. I know that a group at microsoft added a ParallelArray datatype (ftp://ftp.research.microsoft.com/pub/tr/TR-2005-184.pdf) to C# as a way to distinguish the intent (they speed up data-parallel code by compiling it down to your GPU/graphics card). Perl6, being an operator-oriented language, associates the distinction with the operators rather than with the datatype. This is probably a better approach, but it does mean that you need an operator whenever you want to treat the array as data-parallel. (BTW, data-parallel arrays differ from bags in that they have an ordered index that is preserved across unordered operations) I think you're leaning too far towards concurrency in attempting to address the perceived bias. Probably true ... though I think that the bias is real, it's just a question of if its a good-bias or a bad-bias. Under these circumstances, I would much rather have to explicitly say that I want parallel execution - provided that the ability to do it is there and it's easy to get at and behaves in a sensible manner (naturally this lets you parallelise things the compiler isn't sure are safe to parallelise due to possible side effects. That's fine, since you know which side effects are okay to do that to in your program). Of course, it's not necessarily true that "you know" that something is safe -- often "you think" it's safe but then you get an intermittent failure at runtime,. I would love to be able to tell the compiler "I think this is safe" and have it tell me "you're wrong" as a compile-time error (this is one of the things that an explicit type system is good for). But perhaps Perl is too dynamic a language for that.
Re: Sequential bias in S04 (and Perl6 in general)
Springing out of the ashes (and a job where I have to write Java) for my first post in years: On Fri, 04 Jan 2008 13:13:11 -0800, Dave Whipp <[EMAIL PROTECTED]> wrote: > I agree that adding a parallel "forall" (and similar statements) via a > pragma will be easy if the appropriate underlying machinery is there, so > maybe I can live with the bias in S04 -- perhaps rename it to > "Sequential Blocks and Statements". Anywhere that we guarantee > sequential behavior, we pretty much rule out concurrency. But if we > maximize the number of places where we are explicitly "unordered" then > we also maximize the number of places where implicit concurrency can be > added later. From that perspective, it's unfortunate a C loop > always iterates arrays in the order of their indices. I wouldn't agree with that at all. I think of arrays as ordered constructs, so I'd want the default iteration over my array to happen in the order of the indices. I wouldn't have a problem with having the ability for C to iterate over a bag or some other inherently unordered, unsorted container in arbitrary possibly-parallel order though. Possibly by default, if the compiler can be satisfied that the closure's not got any unpleasant side effects to interfere with parallel execution. I think you're leaning too far towards concurrency in attempting to address the perceived bias. A lot of the time, the compiler's not going to be able to prove that it's safe to autothread a given closure because it might have side effects. If we were talking about Haskell or some other language which is ordinarily pure, things would be different. Under these circumstances, I would much rather have to explicitly say that I want parallel execution - provided that the ability to do it is there and it's easy to get at and behaves in a sensible manner (naturally this lets you parallelise things the compiler isn't sure are safe to parallelise due to possible side effects. That's fine, since you know which side effects are okay to do that to in your program). Matthew
Re: Sequential bias in S04 (and Perl6 in general)
Larry Wall wrote: my hope is that we can delegate locking entirely to the innards of the implementation and never mention it at all on the language level. Hmm, sounds to me analogous to hoping that type inference will avoid the need to expose type-annotations at the language level (synchronization constraints can be seen as an extension the type system -- that is, the formal theory that defines what it means for a program to be well behaved). Even if it is possible to infer everything automagically, it is still useful for the user to reinforce the inference with explicit, precise, declarations: makes things faster, and avoids pathological corner cases. Plus it catches errors. Which I guess is why perl6 provides a user-visible explicit typing system. Even if locking itself remains under-the-hood, the constraints that imply the locking need to be user-visible. S03 says that a hyperoperator is a promise that the operator is parallelizable; but that promise implies that the author has taken care of any sync issues in the side effects. It cannot simultaneously be both a promise that the code is safe, and a demand that that compiler add locking to make it safe.
Re: Sequential bias in S04 (and Perl6 in general)
Larry Wall wrote: > I (impersonally) believe that hyper context is the right solution to > this because context can propagate to where it needs to dynamically. > As for the fact that it's not the default list context for "for", > that could easily be changed with a pragma. Maybe that could even > be the default someday, but we have to educate people to think about > "hyper" first. As I just indicated, I'm a mere mortal; so some of the terminology you're using here is throwing me. When I hear "hyper context", my gut instinct is to think "he's advocating some sort of application of the hyperoperator". Is that what you mean, or would the substitution of a bag for a list in a "for" statement qualify as "hyper context"? Or maybe you mean something like the use of a junction in a "given" statement as the parallelized equivalent of a "for" statement? for @x { ... } # executes the block for each element of @x in series given all(@x) { ... } # executes the block for each element of @x in parallel > As for the other part of the proposal, a parallel smartmatch would > need new comb syntax for the compound pattern--I wouldn't overload > given/when for that. Or maybe just make a way to attach a mapreduce > action to any leg of a junction or hyperoperator. Again, I'm not up on the terminology being used here. But if I'm getting the gist of it right, the following is in the spirit of what you're suggesting: Introduce a function that does given/when-type smart-matching, but geared around pattern/code Pairs: e.g., match $x: 1..3 => { dothis() }, 4..6 => { dothat() } # equivalent to: given $x { when 1..3 { dothis() } when 4..6 { dothat() } } Then you could use a junction of Pairs in place of a single Pair to smart-match the patterns in parallel: match $x: 1..3 => { dothis() } & 2..4 => { dothat() } # smart-matches 1..3 and 2..4 in parallel > In any case, we need > to make sure it's easy to place such a parallel comb of matchers at the > pointy end of a feed, and if the source of the feed is also executing > in parallel, make sure the feed can be optimized to a full crossbar > based on packet destination. In the above example, you might say: @x».match 1..3 => { dothis() } & 2..4 => { dothat() } or match any(@x): 1..3 => { dothis() } & 2..4 => { dothat() } in order to get a full crossbar. > It's also possible that we should discourage syntactic parallel > matching in favor of parallel polymorphic dispatch, given that > signatures can also express patterns. Might need to tweak the current > multiple dispatch rules a bit though if we want dispatch ambiguity > to express nondeterminism. In any case, real mapreduce situations > are often generated dynamically, and cannot easily be expressed in > a syntactically fixed set of options. No idea what you're talking about here. -- Jonathan "Dataweaver" Lang
Re: Sequential bias in S04 (and Perl6 in general)
Dave Whipp wrote: > No, you're not the only person thinking Occam ... though I should point > out that none of my suggestions are "par" blocks -- a par block made > every statement within the block execute in parallel with the other > statements in that block (much like a Verilog fork/join pair). No; that was me. Although, as Luke pointed out, I wasn't thinking "parallel execution" so much as "arbitrarily ordered execution" (which, as Dave points out, is a prerequisite for true parallel execution). Paul Seamons wrote: > > I disagree with the idea that humans don't think concurrently (though > > more often they think in terms of data dependencies). > > I think this is more analogous to event based programming rather than parallel > programming. Event based and parallel based have some similarities but the > are fundamentally different. Humans typically interact with events and only > occasionally are able to walk and chew gum at the same time. As a human (as opposed to that weird creature known as a "professional programmer"), I tend to do one thing at a time, though I'm more than capable of prioritizing a set of tasks that are handed to me, even if new tasks are added to my workload while I'm still working on others. And if I'm working as part of a team, I know how to delegate tasks to others. As Dave points out, it isn't parallelism that's hard so much as it is coordination with the rest of the team in order to prevent conflicts involving shared resources. -- Jonathan "Dataweaver" Lang
Re: Sequential bias in S04 (and Perl6 in general)
On Fri, Jan 04, 2008 at 01:13:11PM -0800, Dave Whipp wrote: > From that > perspective, it's unfortunate a C loop always iterates arrays in the > order of their indices. But it doesn't, in hyper context. In Perl 6, C and C are really the same thing, and both respond to hyper context. > As I see it, parallelism is easy: it's synchronization that's hard. > Specifically, it's hard to get exactly the right scoping of constraints. > And it seems to me that "hyper" addresses the parallelization aspect but > not synchronization. Concurrency.pod (S17) defines a few basic mechanisms, > but it's not obvious that they're really "easy", or sufficiently > declarative. There seem to be synchronization scopes analogous to "state" > and to hypotheticals, but not "my", "our", "temp", and "has". (I'm not sure > exactly what primitives are needed: we could discover that by doing more > parallel programming ... which won't happen unless it's easy) My only feeling on the matter currently is that C and C are probably evil when used on anything shareable, whereas lexicals and contextual vars are probably better behaved. But I'm quite certain people will be playing with the declarative parallelism we've already put in via hyperops, junctions, and feeds, not to mention transactions to manage cooperating events. > The way humans seem to work is that they'll say "I'll do this and this > separately, but I won't worry about that unless something goes wrong". We > employ a mixture of course grain threading, fine grain locking, exceptions, > and recoverable transactions; that we juggle dynamically. That's pretty > hard to do when writing a program, which is why I want to place the burden > on the language designer, not the language user. Sure, my hope is that we can delegate locking entirely to the innards of the implementation and never mention it at all on the language level. STM may or may not be the solution to that. Exceptions are also evil when it comes to concurrency; that's why we've gone to great pains to allow unthrown exceptions to be returned as data when failures occur. You really, really don't want your hyperops throwing exceptions just because one value in a million was bogus. >> With Perl 6 we're trying to make the opposite mistake. > > I fear you may be successfully underemphasizing one dimension to the > detriment of others :-). But considering that you do a pretty good job most > of the time, I'm not too worried. Well, I don't profess to be omniscient, or even prescient. All I can point out is that I'm also trying very hard to make a language that can mutate away from Evil and towards Good, however they choose to define themselves in the cybersphere this year. And that is why grammars must do completely fair longest-token matching across all base and derived grammars (maybe even in parallel :). It is a mistake to privilege either the old over the new or the new over the old, to the extent that they can coexist. In ecological terms, I hope Perl 6 will have a very wide gene pool. Larry
Re: Sequential bias in S04 (and Perl6 in general)
Larry Wall wrote: It's really, really easy to misdesign a computer language by overemphasizing one particular design dimension to the detriment of others. I agree that adding a parallel "forall" (and similar statements) via a pragma will be easy if the appropriate underlying machinery is there, so maybe I can live with the bias in S04 -- perhaps rename it to "Sequential Blocks and Statements". Anywhere that we guarantee sequential behavior, we pretty much rule out concurrency. But if we maximize the number of places where we are explicitly "unordered" then we also maximize the number of places where implicit concurrency can be added later. From that perspective, it's unfortunate a C loop always iterates arrays in the order of their indices. As I see it, parallelism is easy: it's synchronization that's hard. Specifically, it's hard to get exactly the right scoping of constraints. And it seems to me that "hyper" addresses the parallelization aspect but not synchronization. Concurrency.pod (S17) defines a few basic mechanisms, but it's not obvious that they're really "easy", or sufficiently declarative. There seem to be synchronization scopes analogous to "state" and to hypotheticals, but not "my", "our", "temp", and "has". (I'm not sure exactly what primitives are needed: we could discover that by doing more parallel programming ... which won't happen unless it's easy) The way humans seem to work is that they'll say "I'll do this and this separately, but I won't worry about that unless something goes wrong". We employ a mixture of course grain threading, fine grain locking, exceptions, and recoverable transactions; that we juggle dynamically. That's pretty hard to do when writing a program, which is why I want to place the burden on the language designer, not the language user. With Perl 6 we're trying to make the opposite mistake. I fear you may be successfully underemphasizing one dimension to the detriment of others :-). But considering that you do a pretty good job most of the time, I'm not too worried.
Re: Sequential bias in S04 (and Perl6 in general)
Joe Gottman schreef: > if code that should be processed concurrently > is instead processed sequentially, the results will be correct Not if parallel sampling of happening stuffs is involved. All of your thousands of temperature sensors in your nuclear factory, all running the same code, should not wait for any of their neighbours. They should interrupt their supervisor if something interesting was detected, by setting a bit in some register, so the supervisor can serially check any interrupts. But even the supervisor could be multiple devices doing that concurrently. > though the program will take longer to run than necessary. Not if there is only 1 "processor", because then the overhead of interleaving processes will make the concurrent processing take longer. -- Groet, Ruud
Re: Sequential bias in S04 (and Perl6 in general)
I (impersonally) believe that hyper context is the right solution to this because context can propagate to where it needs to dynamically. As for the fact that it's not the default list context for "for", that could easily be changed with a pragma. Maybe that could even be the default someday, but we have to educate people to think about "hyper" first. As for the other part of the proposal, a parallel smartmatch would need new comb syntax for the compound pattern--I wouldn't overload given/when for that. Or maybe just make a way to attach a mapreduce action to any leg of a junction or hyperoperator. In any case, we need to make sure it's easy to place such a parallel comb of matchers at the pointy end of a feed, and if the source of the feed is also executing in parallel, make sure the feed can be optimized to a full crossbar based on packet destination. (And just as in the case of optimizing given/when to a jump table, this also implies that smartmatching must be assymetrical, not symmetrical. It's just the "jump" in this case is a packet routing rather than program counter routing.) It's also possible that we should discourage syntactic parallel matching in favor of parallel polymorphic dispatch, given that signatures can also express patterns. Might need to tweak the current multiple dispatch rules a bit though if we want dispatch ambiguity to express nondeterminism. In any case, real mapreduce situations are often generated dynamically, and cannot easily be expressed in a syntactically fixed set of options. And overriding all of this is how to hide all this cool stuff so that it A) doesn't drive newbies mad, but B) is right there at their fingertips when they need it, and C) is easily recognizable as magic so that when they see it in other people's code they'll understand that they don't understand. That's why hyper context is an explicit feature in standard Perl 6. But then, so is the ability to add a pragma like: use hyper; It's really, really easy to misdesign a computer language by overemphasizing one particular design dimension to the detriment of others. With Perl 6 we're trying to make the opposite mistake. Larry
Re: Sequential bias in S04 (and Perl6 in general)
> I disagree with the idea that humans don't think concurrently (though > more often they think in terms of data dependencies). I think this is more analogous to event based programming rather than parallel programming. Event based and parallel based have some similarities but the are fundamentally different. Humans typically interact with events and only occasionally are able to walk and chew gum at the same time. Though not fully specified, Perl 6 will have as all the tools necessary to make event driven programs - but there isn't a way to do so automatically. It will take work. I'd argue the same is true for parallel. Paul
Re: Sequential bias in S04 (and Perl6 in general)
Mark J. Reed wrote: Am I the only one having bad flashbacks to Occam, here? (Transputing Will Change Everything!) My $0.02, FWIW: Concurrency is surprising. Humans don't think that way. And programs aren't written that way - any program represented as a byte stream is inherently sequential in nature. ... No, you're not the only person thinking Occam ... though I should point out that none of my suggestions are "par" blocks -- a par block made every statement within the block execute in parallel with the other statements in that block (much like a Verilog fork/join pair). I disagree with the idea that humans don't think concurrently (though more often they think in terms of data dependencies). If I ask someone to boil a kettle + make a cup of tea, and open a can of dogfood to feed the dog, they'd probably sequence the operations such that the kettle comes to the boil while they're feeding the dog ... they'll probably put teabags in the teacups concurrently, too. If you get a group of people together to achieve some goal (e.g. restore an old building) then the first thing they'll do is to partition the work so that team members can work in parallel. The fact that programs aren't written that way is something that I think needs to change. Though, if done right, then things probably don't need to change too much. A program is not a simple byte stream: it's a random-access array. Multiple cores imply multiple physical program counters. If we assume that the core count will double every 18 months, then three years from now we'll be seeing 32-core machines quite regularly. I wouldn't be surprised to see this grow even faster (Moore's Law doesn't apply to architectural shifts).
Re: Sequential bias in S04 (and Perl6 in general)
Am I the only one having bad flashbacks to Occam, here? (Transputing Will Change Everything!) My $0.02, FWIW: Concurrency is surprising. Humans don't think that way. And programs aren't written that way - any program represented as a byte stream is inherently sequential in nature. Where the system can detect opportunities for parallel execution, great, but you have to be careful. Automatic concurrency should only happen when it doesn't change the results at all (apart from making them appear faster). When I want things to be explicitly parallel in a way that can interfere with the apparent flow of execution, that should be a Big Red Blinking Border around the code, not something subtle like "forall" instead of "foreach" or doubled curlies.
Re: Sequential bias in S04 (and Perl6 in general)
Luke Palmer wrote: forall was about concurrency, not order of evaluation. There is a difference between running in an arbitrary order serially and running in parallel. for %bag { .say; } If the bag had elements "hello", "world", I think printing: helworld lo Would definitely count as violating the principle of least surprise. For the specific case of C, I think that its implementation should probably be "is critical" -- The C method is designed for simple user messages, and atomicity is probably as useful as the auto-newline for its intended usage. But your general message still stands: concurrency can surprise if not handled properly. Just thinking out load, perhaps one could say that the following constructs are broadly equivalent: * for %bag { .say }; * forall %bag { is locally_critical; .say }; (lets assume for now that "is locally_critical" is like "is critical" but protects only against child-threads of the ::OUTER scope) Now lets change the definition of curlies such that they always imply this modified "is locally_critical" trait. Now, the following would be equivalent: * for %bag { .say }; * forall %bag { isnt locally_critical; .say }; From here I'll just make one more proposal: a new form of curley: * for %bag { .say }; // unordered sequential ("locally_critical") * for %bag {{ .say }}; // unordered concurrent (not "locally_critical") With these modified forms of braces it becomes much easier to define safe concurrent control structures: the default curlies force the additional safety yet there's a simple alternative that increases concurrency without requiring a new statement (but one would still need a special form of splat operator to morph a sequential container for unordered iteration -- so maybe the general unordered "forall" statement would still be useful)
Re: Sequential bias in S04 (and Perl6 in general)
On Jan 4, 2008 9:18 AM, Jonathan Lang <[EMAIL PROTECTED]> wrote: > Joe Gottman wrote: > >On the other hand, this being Perl, I do believe it should be easy to > > specify the concurrent case. I think that a keyword (and a > > keyword corresponding to ) would be a good idea. > > These would not be quite parallel to and because there > > would be some subtle differences arising from the concurrent > > processing. For instance, probably should not be used with > > , because should stop subsequent iterations and the > > subsequent iterations could already have occurred when it is called. > > Similarly, should not be used with , because the > > next case might already have been checked when is called. > > I don't think that there's need for a 'forall' keyword. Note that > Perl 6 has both Lists and Bags, the difference being that a List is > ordered while a Bag isn't. So what happens when you feed a Bag into a > "for" statement? Conceptually, you'd expect to get evaluation across > its members with no promises concerning the order of evaluation. forall was about concurrency, not order of evaluation. There is a difference between running in an arbitrary order serially and running in parallel. for %bag { .say; } If the bag had elements "hello", "world", I think printing: helworld lo Would definitely count as violating the principle of least surprise. Luke
Re: Sequential bias in S04 (and Perl6 in general)
Joe Gottman wrote: >On the other hand, this being Perl, I do believe it should be easy to > specify the concurrent case. I think that a keyword (and a > keyword corresponding to ) would be a good idea. > These would not be quite parallel to and because there > would be some subtle differences arising from the concurrent > processing. For instance, probably should not be used with > , because should stop subsequent iterations and the > subsequent iterations could already have occurred when it is called. > Similarly, should not be used with , because the > next case might already have been checked when is called. I don't think that there's need for a 'forall' keyword. Note that Perl 6 has both Lists and Bags, the difference being that a List is ordered while a Bag isn't. So what happens when you feed a Bag into a "for" statement? Conceptually, you'd expect to get evaluation across its members with no promises concerning the order of evaluation. Likewise, I wonder if there might be a more general way to handle the 'givenall' concept. Say, by marking a block as being concurrent (i.e., parallel) in nature rather than sequential (i.e., series). That is, you normally evaluate a block's statements in order from the first to the last; marking the block as concurrent would tell the parser that the order of evaluation within this block isn't important. If a block of "when" statements is parallelized in this manner, you get the effect of the proposed 'givenall' keyword without the inherent restrictions that requiring the keyword would impose. -- Jonathan "Dataweaver" Lang
Re: Sequential bias in S04 (and Perl6 in general)
Dave Whipp wrote: I was reading Synopsis 4 with regards to multi core programming. It seems to be infused with a bias towards non-parallel models of computation. Concurrently appears to be an add-on feature -- whereas we should have a mindset that explicit sequential constraints are the add-on feature. Two statements that are missing from S04 (feel free to change the names) are C; and a form of C that tests/executes multiple C clauses in arbitrary order (without needing the sequential C statement). forall @a -> $x { ... } runs the code block on each element of @a (no defined order). If @a is a lazy generator then generation of values is concurrent with running the code block on those generated values). forall @a -> $x : sequential { ... } forces an additional sequential constraint on the execution, such that the Nth element of @a is not obtained until the code block has executed for the (N-1)th. C is an alias for this constrained variant. C implies this sequential constraint to avoid surprising legacy (perl5) programmers. Similarly, C, C, C, C, ... should all accept this ":sequential" adverb to force them to iterate their lists sequentially -- and should otherwise iterate in arbitrary/concurrent order. given $x :all { ... } would run the code blocks of all C statements (in the C block) which smart-match true against $x. The ":sequential" adverb would be used to constrain execution of the C blocks to run in the order they appear in the source code. (it would be good if the current C could be thought of as using a ":first" modifier, which runs the code block of the lexically first C clause that evaluates to true -- but which potentially tests multiple C clauses in parallel. Unfortunately the current language definition is much too sequential for this viewpoint) I think a major reason for the bias toward sequential processing is that if code that should be processed sequentially is instead processed concurrently then the results will almost always be incorrect. Conversely, if code that should be processed concurrently is instead processed sequentially, the results will be correct though the program will take longer to run than necessary. I don't think it's unreasonable to prefer always correct but slow to sometimes incorrect and fast, especially if it is difficult to automatically tell which cases might result in incorrect behavior. On the other hand, this being Perl, I do believe it should be easy to specify the concurrent case. I think that a keyword (and a keyword corresponding to ) would be a good idea. These would not be quite parallel to and because there would be some subtle differences arising from the concurrent processing. For instance, probably should not be used with , because should stop subsequent iterations and the subsequent iterations could already have occurred when it is called. Similarly, should not be used with , because the next case might already have been checked when is called. Joe Gottman
Re: Sequential bias in S04 (and Perl6 in general)
Moritz Lenz wrote: You can achieve that with the "hyper" list-op (see S02). Also note that an optimizer is free to automatically add the "hyper" list op if it can prove that the executed block has no side effects. Yes, there are some places where things are better than others, which is why I called out S04 specifically. The concern I have is that it is necessary to use a "functional" subset to explicitly tell Perl6 that I want it to do the right thing on many-core systems. The bias that I see is the perceived need to say that hypers (and junctions) may "auto-thread", without needing to be explicit that control statements "auto-sequentialize". That latter is assumed, but the former is explicit: this asymmetry is the bias. In as much as it is possible to talk about core features for Perl6, the control structures of S04 are "core". Given generic iteration and selection mechanisms that are unbiased with respect to concurrency, it is moderately straight forward to define the sequentially constrained versions as an "add on" feature. The reverse is more difficult: concurrency as an add-on feature is hard. That sounds really like a bad idea for simple "just do it" scripts. Just imagine explaining concurrency issue to a beginner who is not even confident with variables and blocks... Just like hyper-operators, the form of the statements that are less biased towards sequentialization need not be dangerous for beginners, if the language design is careful. One could start simply by defining the order of iteration to be undefined, and adding a form that does guarantee the order for those cases where it does matter. From there, it is a fairly small jump from "unordered" to "concurrent", assuming the bulk of the language has semantics that preserve safety for concurrent operations (admittedly, a non-trivial assumption).
Re: Sequential bias in S04 (and Perl6 in general)
At 5:22 PM -0800 1/2/08, Dave Whipp wrote: I was reading Synopsis 4 with regards to multi core programming. It seems to be infused with a bias towards non-parallel models of computation. Concurrently appears to be an add-on feature -- whereas we should have a mindset that explicit sequential constraints are the add-on feature. I agree with this idea in principle. Most of the time when people are working with lists, the tasks being done aren't conceptually dependent on being executed in a certain order, even if for some (sequences/arrays) it is important to reassemble results in corresponding order to the inputs. Needing things to seemingly execute in a certain order only really matters when I/O with extra-process entities like the user is involved, I think. Or if the output of one iteration is an input for another, which is rare I think. Realistically, the user will want to be lazy and will tend to default to shorter versions of things, so making all possible list handling tasks non-sequential by default is good huffman coding. As an aside, one design decision I made in my Muldis D language (for relational DBMSs, whose spec is on CPAN) was to have a clear separation of concerns. The language has both functional and procedural aspects, and each routine you define in the language is just one or the other. A function is pure functional and has no side-effects (no monads even), and sees no globals, has no variables. Most code one would write would be functional, and so most code gets implicit autoparallelization. Since there are no side effects here, it is implicitly safe. A procedure is pure-ish procedural, and each statement in it executes (conceptually) in sequence following the previous one, it sees globals and has side effects. Bridging the 2 is a multi-update operator; it is like an assignment statement targeting N procedure vars; procedures only invoke functions by way of update operators, as functions are the arguments of the latter, functions don't invoke non-functions. Now, I realize that for Perl 6 to adopt such an approach as this may be undesirable to the majority, since afaik Perl 6 wants every kind of routine to be able to have side-effects, as per Perl 5 and many other languages, so to maximize the TIMTOADY factor. But if it *were* possible in Perl 6 to mark routines, or have routine kinds, that are forbidden from side-effects, which extends to anything they invoke, then this is also a huffman-efficient and easy to use way to auto-parallelize. Maybe either have a new routine declaration keyword, or maybe a :pure trait? Or conversely have that be the default and have an :impure trait on the others. Where those things aren't just implied by other things. Note that supporting this wouldn't change the language much per se, but essentially be a flag to the compiler to be more strict about some things within the scope of the routine declaration, and therefore be more confident that it is safe to use some optimizations. -- Darren Duncan
Re: Sequential bias in S04 (and Perl6 in general)
Dave Whipp wrote: > I was reading Synopsis 4 with regards to multi core programming. It > seems to be infused with a bias towards non-parallel models of > computation. Concurrently appears to be an add-on feature -- whereas we > should have a mindset that explicit sequential constraints are the > add-on feature. That sounds really like a bad idea for simple "just do it" scripts. Just imagine explaining concurrency issue to a beginner who is not even confident with variables and blocks... > Two statements that are missing from S04 (feel free to change the names) > are C; and a form of C that tests/executes multiple > C clauses in arbitrary order (without needing the sequential > C statement). > > >forall @a -> $x { ... } > > runs the code block on each element of @a (no defined order). You can achieve that with the "hyper" list-op (see S02). Also note that an optimizer is free to automatically add the "hyper" list op if it can prove that the executed block has no side effects. ... > Similarly, C, C, C, C, ... should all > accept this ":sequential" adverb to force them to iterate their lists > sequentially -- and should otherwise iterate in arbitrary/concurrent order. Some of this can be written with hyper ops, just as the dot for method calls has a "hyper dot" Object>>.method > I'm not too concerned about the exact details: my point is that we > should be fully aware of the fact that perl6 will be released into a > multicore (some people use the term many-core for devices with hundreds > of cores) world, and that exploitation of these parallel resources > should be the default (easy) behavior. We shouldn't have a "concurrency" > synopsis (we don't -- but we do have Spec/concurrency.pod). Instead, we > should have "sequential.pod" that defines how to impose additional > sequential constraints (e.g. ":atomic", ":sequential") on top of the > those inferred from data dependencies. I think that the concurrency synopsis is still useful for explicit threading, STM and the like. Also note that Perl 6 tries to preserver Perl's soul, and is not an Erlang based language ;-) Cheers, Moritz -- Moritz Lenz http://moritz.faui2k3.org/ | http://perl-6.de/ signature.asc Description: OpenPGP digital signature
Sequential bias in S04 (and Perl6 in general)
I was reading Synopsis 4 with regards to multi core programming. It seems to be infused with a bias towards non-parallel models of computation. Concurrently appears to be an add-on feature -- whereas we should have a mindset that explicit sequential constraints are the add-on feature. Two statements that are missing from S04 (feel free to change the names) are C; and a form of C that tests/executes multiple C clauses in arbitrary order (without needing the sequential C statement). forall @a -> $x { ... } runs the code block on each element of @a (no defined order). If @a is a lazy generator then generation of values is concurrent with running the code block on those generated values). forall @a -> $x : sequential { ... } forces an additional sequential constraint on the execution, such that the Nth element of @a is not obtained until the code block has executed for the (N-1)th. C is an alias for this constrained variant. C implies this sequential constraint to avoid surprising legacy (perl5) programmers. Similarly, C, C, C, C, ... should all accept this ":sequential" adverb to force them to iterate their lists sequentially -- and should otherwise iterate in arbitrary/concurrent order. given $x :all { ... } would run the code blocks of all C statements (in the C block) which smart-match true against $x. The ":sequential" adverb would be used to constrain execution of the C blocks to run in the order they appear in the source code. (it would be good if the current C could be thought of as using a ":first" modifier, which runs the code block of the lexically first C clause that evaluates to true -- but which potentially tests multiple C clauses in parallel. Unfortunately the current language definition is much too sequential for this viewpoint) I'm not too concerned about the exact details: my point is that we should be fully aware of the fact that perl6 will be released into a multicore (some people use the term many-core for devices with hundreds of cores) world, and that exploitation of these parallel resources should be the default (easy) behavior. We shouldn't have a "concurrency" synopsis (we don't -- but we do have Spec/concurrency.pod). Instead, we should have "sequential.pod" that defines how to impose additional sequential constraints (e.g. ":atomic", ":sequential") on top of the those inferred from data dependencies. Even "threads" should actually be viewed as an explicit sequential construct, and not as a construct for parallelization. The default (easy) way of coding should exploit the available compute resources. Telling the execution engine how to map the computation onto N sequential resources is a constraint (optimization) that reduces parallelism. I'm not asking anyone to implement any concurrency beyond what is currently planned for perl 6.0.0: I ask only for the language definition to avoid making unnecessary guarantees of sequential behavior. "sequential" is a perfectly reasonably interpretation of "arbitrary/concurrent" ordering. I'd be happy to go through and scrub the docs, if there was consensus that it would be correct to do so. Unfortunately, doing so would probably increase the future brittleness of the test suite -- because existing tests may assume sequential behaviors, and it's difficult to test for robustness against arbitrary ordering without actually implementing arbitrary ordering. Dave.
Error in S04
In the "Multiplicative Precedence" section of S04, "div" is specified twice. Joe Gottman
Re: S04 - forbidden coding-style
Am Mittwoch, 26. Juli 2006 03:18 schrieb Ruud H.G. van Tol: > Thomas Wittek schreef: > > > > What I wanted to say is that it would annoy me, if almost all > > operators and control-flow keywords are lowercase but a hand full of > > them has to be written uppercase. Hi, I suppose the above is a statement, true for quite a number of hackers. > returnif $something, $foo ; > > return.if $something, $foo ; > > $something and return $foo ; From all appended characters suggested so far, the comma seems to be the most natural notation and that is big part of what Perl was to me in past: Making programming as natural in terms of expressing language as possible. So in my eyes, do { $Worker.work() }, until $Day.letsCallItA(); return $Change, unless $Payment == $Price; or loop { $Stuff.Do() } , while $TheresStuffToDo; seems to be the most natural change in syntax, if $WeReallyWantToAvoidTheBackslash ;) I'm afraid though, it is also the most nasty one for parser-developers as you cannot tell the difference between this and an expression very early... ??? Regards and many thanks for making Perl6!!! -- Udo Güngerich Grabenstr. 21 35396 Gießen f: 0177 7495927 e: [EMAIL PROTECTED] w: http://www.udo-guengerich.de
[patch] typos in S04
This is a patch for S04. Special thanks go to cjeris++ and other kind persons on #perl6 for reviewing this. Cheers, Agent Index: D:/projects/Perl6-Syn/S04.pod === --- D:/projects/Perl6-Syn/S04.pod (revision 10479) +++ D:/projects/Perl6-Syn/S04.pod (working copy) @@ -23,7 +23,7 @@ Every block is a closure. (That is, in the abstract, they're all anonymous subroutines that take a snapshot of their lexical scope.) -How any block is invoked and how its results are used is a matter of +How a block is invoked and how its results are used are matters of context, but closures all work the same on the inside. Blocks are delimited by curlies, or by the beginning and end of the @@ -41,7 +41,7 @@ A bare closure without placeholder arguments that uses C<$_> (either explicitly or implicitly) is treated as though C<$_> were a -a formal parameter: +formal parameter: $func = { print if $_ }; # Same as: $func = -> $_ { print if $_ }; $func("printme"); @@ -473,7 +473,7 @@ cases.) Here "abnormal" means any transfer of control outward that is not just falling off the end of a block. A C, for example, is considered a form of abnormal control flow, since it -can jump out of multiple levels of closure to the end of the scope +can jump out of multiple levels of closures to the end of the scope of the current subroutine definition. Loop commands like C are abnormal, but looping because you hit the end of the block is not. The implicit break of a C block is abnormal. @@ -507,7 +507,7 @@ leave <== :foo:bar:baz(1) if $leaving; -or going the other way:: +or going the other way: $leaving and :foo:bar:baz(1) ==> leave; @@ -521,7 +521,7 @@ scope of that loop, and if that call mentions the outer loop's label, then that outer loop is the one that must be controlled. (This search of lexical scopes is limited to the current "official" subroutine.) -If there is no such lexically scoped outer loop in current subroutine. +If there is no such lexically scoped outer loop in the current subroutine. Then a fallback search is made outward through the dynamic scopes in the same way Perl 5 does. (The difference between Perl 5 and Perl 6 in this respect arises only because Perl 5 didn't have user-defined @@ -568,7 +568,7 @@ of parameters. (Initialization of ordinary variables does not count--presumably the presence of a label will prevent code-movement optimizations past the label.) So, for instance, it's always possible -to goto into the next case of a C or into either the "then" +to C into the next case of a C or into either the "then" or "else" branch of a conditional. You may not go into a C or a C, though, because that would bypass a formal parameter binding (not to mention list generation in the case of C). @@ -580,7 +580,7 @@ As in Perl 5, many built-in functions simply return undef when you ask for a value out of range, or the function fails somehow. Perl 6 has -C objects, which refers to an unthrown C object in +C objects, any of which refers to an unthrown C object in C<$!> and knows whether it has been handled or not. If you test a C for C<.valid>, C<.defined> or C<.true>, it causes @@ -594,7 +594,7 @@ default argument. At scope exit, C<$!> discards all handled exceptions from itself, then performs -a GC check for all remaining (unhandled) exceptions. If all of them are still +a GC (Garbage Collection) check for all remaining (unhandled) exceptions. If all of them are still alive (e.g. by becoming part of the return value), then they are appended to C<< CALLER::<$!> >>. Otherwise, it calls C to throw those exceptions as a single new exception, which may then be caught with a C block in @@ -672,13 +672,13 @@ All of these trait blocks can see any previously declared lexical variables, even if those variables have not been elaborated yet when -the closure is invoked. (In which case the variables evaluate to an -undefined value.) +the closure is invoked (in which case the variables evaluate to an +undefined value). Note: Apocalypse 4 confused the notions of C/C with C/C. These are now separate notions. C and C are used only for their side effects. C and C must return boolean values that are -evaluated according to the usual Design by Contract rules. (Plus, +evaluated according to the usual Design by Contract (DBC) rules. (Plus, if you use C/C in a class block, they only execute when the class block is executed, but C/C in a class block are evaluated around every method in the class.) @@ -718,7 +718,7 @@ opening brace. You I parenthesize the expression if there is a bare block or pointy block that would be misinterpreted as the statement's block. This is regardless of whether a term or operator is expected where -the block occurs. (A block inside bracket
Re: S04 - forbidden coding-style
Thomas Wittek schreef: > Actually I don't know all of them but most seem to be (part of) > identifiers, not operators. Of course they are reserved words. > > What I wanted to say is that it would annoy me, if almost all > operators and control-flow keywords are lowercase but a hand full of > them has to be written uppercase. > > It would be especially annoying, if a keyword like "if" exists in both > lower and upper case. Besides the fact that is looks ugly and is a bit > harder to type, imho ;) returnif $something, $foo ; return.if $something, $foo ; $something and return $foo ; -- Groet, Ruud
Re: S04 - forbidden coding-style
Markus Laire schrieb: >> Operators/reserved words should be lowercase. Period. ;) >> I think that this would heavily break consistency, annoying new users. > > There are already many uppercase reserved words in perl6: > > Pseudo-packages from S02 > MY, OUR, GLOBAL, OUTER, CALLER, CONTEXT, SUPER, COMPILING > Closure traits from S04 > BEGIN, CHECK, INIT, END, FIRST, ENTER, LEAVE, KEEP, > UNDO, NEXT, LAST, PRE, POST, CATCH, CONTROL > From S10 > AUTODEF, CANDO > Submethods from S12 > BUILD, BUILDALL, CREATE, DESTROY, DESTROYALL > Pseudo-class from S12 > WALK > I might've missed some. > > So making statement modifiers uppercase would just be an another place > where perl6 uses uppercase reserved words. Actually I don't know all of them but most seem to be (part of) identifiers, not operators. Of course they are reserved words. What I wanted to say is that it would annoy me, if almost all operators and control-flow keywords are lowercase but a hand full of them has to be written uppercase. It would be especially annoying, if a keyword like "if" exists in both lower and upper case. Besides the fact that is looks ugly and is a bit harder to type, imho ;) -Thomas
[patch] S04: CATCH blocks
(This paragraph may need some more treatment but I won't attempt it until I grasp the content better.) * agentzh++ noticed confusing language regarding two kinds of scope in S04. --- design/syn/S04.pod (revision 10465) +++ design/syn/S04.pod (working copy) @@ -456,7 +456,7 @@ of the C block. Handled exceptions break out past this implicit rethrow.) -A C block sees the lexical scope in which it defined, but the +A C block sees the lexical scope in which it is defined, but the dynamic scope in which it is called, that is, as if it were called from the dynamic location that threw the exception. That is, the stack is not unwound until some exception handler chooses to -- Gaal Yahas <[EMAIL PROTECTED]> http://gaal.livejournal.com/
Re: S04 - forbidden coding-style
On 7/25/06, Thomas Wittek <[EMAIL PROTECTED]> wrote: > Bearing that in mind, would the eye-socket-burning > > return $foo > IF $something; > > really be so bad? Operators/reserved words should be lowercase. Period. ;) I think that this would heavily break consistency, annoying new users. perhaps this can be enabled with a pragma? i suggest C ~jerry :)
Re: S04 - forbidden coding-style
On 7/25/06, Thomas Wittek <[EMAIL PROTECTED]> wrote: > Bearing that in mind, would the eye-socket-burning > > return $foo > IF $something; > > really be so bad? Operators/reserved words should be lowercase. Period. ;) I think that this would heavily break consistency, annoying new users. There are already many uppercase reserved words in perl6: Pseudo-packages from S02 MY, OUR, GLOBAL, OUTER, CALLER, CONTEXT, SUPER, COMPILING Closure traits from S04 BEGIN, CHECK, INIT, END, FIRST, ENTER, LEAVE, KEEP, UNDO, NEXT, LAST, PRE, POST, CATCH, CONTROL From S10 AUTODEF, CANDO Submethods from S12 BUILD, BUILDALL, CREATE, DESTROY, DESTROYALL Pseudo-class from S12 WALK I might've missed some. So making statement modifiers uppercase would just be an another place where perl6 uses uppercase reserved words. -- Markus Laire
Re: S04 - forbidden coding-style
> Bearing that in mind, would the eye-socket-burning > > return $foo > IF $something; > > really be so bad? Operators/reserved words should be lowercase. Period. ;) I think that this would heavily break consistency, annoying new users. -Thomas
Re: S04 - forbidden coding-style
On 7/22/06, Aaron Crane <[EMAIL PROTECTED]> wrote: Larry Wall writes: > Maybe we should just make statement modifiers uppercase and burn out > everyone's eye sockets. :) ... Bearing that in mind, would the eye-socket-burning return $foo IF $something; really be so bad? This has really started to grow on me. I like this idea even if we don't change the rules for end of statement after curlies.
Re: S04 - forbidden coding-style
I know, shoot me -- but just so we've discussed it and put it to bed, maybe :if or _if or fi? --- Aaron Crane <[EMAIL PROTECTED]> wrote: > Larry Wall writes: > > Maybe we should just make statement modifiers uppercase and burn > out > > everyone's eye sockets. :) > > I like statement modifiers, and I want them to continue to exist in > Perl 6. > But it seems to me that a lot of the most awkward decisions about > Perl 6 > syntax are awkward precisely because > > EXPR > if EXPR; > BLOCK > > and > > EXPR; > if EXPR BLOCK > > are so similar. > > Bearing that in mind, would the eye-socket-burning > > return $foo > IF $something; > > really be so bad? > > Alternatively, perhaps it's possible to find some other morphological > or > syntactic device to distinguish statement_modifier: from > statement_control:, for both humans and the compiler. One option > might > be to require an extra token (a postfix complementizer?) before a > statement > modifier. Maybe something like this: > > return $foo > --- if $something; > > -- > Aaron Crane > __ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
Re: S04 - forbidden coding-style
Larry Wall writes: > Maybe we should just make statement modifiers uppercase and burn out > everyone's eye sockets. :) I like statement modifiers, and I want them to continue to exist in Perl 6. But it seems to me that a lot of the most awkward decisions about Perl 6 syntax are awkward precisely because EXPR if EXPR; BLOCK and EXPR; if EXPR BLOCK are so similar. Bearing that in mind, would the eye-socket-burning return $foo IF $something; really be so bad? Alternatively, perhaps it's possible to find some other morphological or syntactic device to distinguish statement_modifier: from statement_control:, for both humans and the compiler. One option might be to require an extra token (a postfix complementizer?) before a statement modifier. Maybe something like this: return $foo --- if $something; -- Aaron Crane
Re: S04 - forbidden coding-style
In a message dated Fri, 21 Jul 2006, Ruud H.G. van Tol writes: Larry Wall schreef: Maybe we should just make statement modifiers uppercase and burn out everyone's eye sockets. :) Or maybe { }. while $x ; Actually, can't that be made to work already (already by the language spec, not by the current compiler featureset) by method Block::while ($block: Bool $true is deferred) { $block() while $true } That would require parens around the boolean expression, though, but I'm sure you can fix that with a parsing constraint. Trey
Re: S04 - forbidden coding-style
Larry Wall schreef: > Maybe we should just make statement modifiers > uppercase and burn out everyone's eye sockets. :) Or maybe { }. while $x ; -- Groet, Ruud
Re: S04 - forbidden coding-style
On Fri, Jul 21, 2006 at 12:07:52PM -0500, Jonathan Scott Duff wrote: : Or just give them some sort of syntactic marker ... I know! : : loop { : ... : } : :while $loopy; : : eat :if $hungry; : go_postal :when $aggravation > 10; : .sleep :until .rested; : : *Everybody* wants the colon! ;-) Well, hmm, I actually thought of that one, but left it out since it's ambiguous when a term is expected (unless we start turning pairs into reserved words too). Larry
Re: S04 - forbidden coding-style
On Thu, Jul 20, 2006 at 10:18:57AM -0700, Larry Wall wrote: > It ain't easy. Maybe we should just make statement modifiers uppercase > and burn out everyone's eye sockets. :) Or just give them some sort of syntactic marker ... I know! loop { ... } :while $loopy; eat :if $hungry; go_postal :when $aggravation > 10; .sleep :until .rested; *Everybody* wants the colon! ;-) -Scott -- Jonathan Scott Duff [EMAIL PROTECTED]
Re: S04 - forbidden coding-style
On Thu, Jul 20, 2006 at 05:03:32PM +0100, Smylers wrote: : Markus Laire writes: : : > S04 seems to say that a style like this can't be used by : > perl6-programmers: : > : > loop : > { : >... : > } : > while $x; : > : > I like this style, as it lines up both the keywords and the curlies. : : As of yesterday you can get very close to this by putting a space-eating : backslash after the closing brace: : : loop :{ : ... :}\ : while $x; : : That still has the keywords and the braces aligned. It's possible we can find a way to dwim that without the backslash, but for now I'd say that check-at-the-end loops are so much rarer than closing braces in general that it's a worthwhile hit even if we end up requiring the backslash on that particular style. The problem with any attempt to dwim it is that loop { ... } while $x {...} looks like the same thing to the parser unless we delay deciding about the "while" until the second {...}, or unless we make blank lines significant (shudder). Alternately, a loop statement always attempts to slurp a subsequent while or until (much like "if" slurps an "else"), and then we rely on the fact that you will get a syntax error as soon as you hit the second {...}, and we force any infinite loop writer to use a semicolon to prevent the the syntax error: loop { ... }; while $x {...} The problem with relying on the syntax error is that every time you rely on a syntax error to find one problem, two offsetting problems can really ruin your day. Suppose they meant the above but said this: loop { ... } while $x{...} So that particular dwim has a robustness strike against it, or at least half a strike. However, I'd guess that "infinite" loops will probably be more common in practice than loop-while, since you tend to write exit-in-the-middle loops using an infinite loop and "last if". We didn't even allow the loop-while form in the initial design of Perl 6, and forced you to write that as an "infinite" loop: loop { ... last unless $x; } Another thing that needs to be said is that we probably should not consider ourselves beholden to a coding style guide designed for a different language with a different lexical structure. We've certainly abandoned C and Unix culture in a number of other areas. We're trying to make a language that will generalize into the future, and that means we want to minimize special cases while making the basic constucts more powerful. Trying to dwym on loop-while may fall into the category of a special case that makes something else error prone. One thing I've tried to guard in the lexical structure of Perl 6 is that there are certain fixed sync points where we can know that something is done with no more than one token of lookahead. Semicolons have traditionally filled that role, and currently line-ending curlies are in the same category. Likewise we try very hard never to give a meaning to two terms in a row, because treating that as an error catches lots of mistakes. An if-else doesn't violate this because else is not something that can occur as the beginning of another statement. Unfortunately, "while" and "until" are in that category... So another possibility is to introduce an else-ish word: loop { ... } mumble while $x; but that that's even longer to type than the backslash "unspace", and doesn't help with statement modifiers in general. So I'm inclined to stick with the backslash for now. 'Course, you can always write your own grammar too--which is something we officially try to encourage but unofficially try to discourage. :) Anyway, despite what I said about abandoning C culture, I like K&R-style bracketing myself, so Perl is naturally a bit prejudiced in that direction. I've only gone more to that style as my eyes have got worse, since it lets me blow up the font and still keep a lot of lines on the page. I think GNU style is wasteful of our natural resources. :) All that being said, I do think the backslash is ugly, so it's possible we might end up biasing the curly rule the other way if the next token looks like a statement modifier. Still thinking about how it will all work in practice, and in particular which failure modes can give very good error messages like "Current line misinterpreted as statement modifier, so previous line's } needs to be }; instead". Or "Current line misinterpreted as statement, so previous line's } needs to be }\ instead". And how often an ambiguous trailing {...} might accidentally occur in a conditional expression... It ain't easy. Maybe we should just make statement modifiers uppercase and burn out everyone's eye sockets. :) Larry
Re: S04 - forbidden coding-style
On 7/20/06, Smylers <[EMAIL PROTECTED]> wrote: Markus Laire writes: > S04 seems to say that a style like this can't be used by > perl6-programmers: > > loop > { >... > } > while $x; > > I like this style, as it lines up both the keywords and the curlies. As of yesterday you can get very close to this by putting a space-eating backslash after the closing brace: loop { ... }\ while $x; That still has the keywords and the braces aligned. Yes. First I didn't like that additional slash, but now that I think it more, it does give a nice visual clue that C belongs to the preceding block. (And that doesn't affect auto-indenting in vim) -- Markus Laire
Re: S04 - forbidden coding-style
Markus Laire writes: > S04 seems to say that a style like this can't be used by > perl6-programmers: > > loop > { >... > } > while $x; > > I like this style, as it lines up both the keywords and the curlies. As of yesterday you can get very close to this by putting a space-eating backslash after the closing brace: loop { ... }\ while $x; That still has the keywords and the braces aligned. Smylers
S04 - forbidden coding-style
This quote from S04 Outside of any kind of expression brackets, a final closing curly on a line (not counting whitespace or comments) always reverts to the precedence of semicolon whether or not you put a semicolon after it. (In the absence of an explicit semicolon, the current statement may continue on a subsequent line, but only with valid statement continuators such as else. A modifier on a loop statement must continue on the same line, however.) seems to say that a style like this can't be used by perl6-programmers: loop { ... } while $x; I'd like to ask if it's necessary to make this programming-style invalid for perl6? This style is used at least by "GNU Coding Standards" (section 5.1) at http://www.gnu.org/prep/standards/standards.html I also like this style, as it lines up both the keywords and the curlies. -- Markus Laire
Re: S04
在 2006/7/1 下午 6:08 時,Tom Allison 寫到: I picked this up at the YAPC and made some markups on it. Apologies that it is not in a diff format, but that's going to come with practice. ... is there a file attachment somewhere? :-) I got stuck on some of the intended behaviors and prohibited behaviors of the 'goto' function. For the purpose of clarity would it be useful to provide a series of specific test cases (in perl 5) to identify what it does today and what (if anything) it will do differently? Yes, that would be very useful. The Pugs t/builtins/control_flow/ goto.t in particular needs to include all the S04 forms; I have sent you a commit bit -- please checkout http://svn.openfoundry.org/pugs with Subversion, add yourself to AUTHORS, and change/augment goto.t to include those test cases. Thanks! Audrey PGP.sig Description: This is a digitally signed message part
S04
I picked this up at the YAPC and made some markups on it. Apologies that it is not in a diff format, but that's going to come with practice. I got stuck on some of the intended behaviors and prohibited behaviors of the 'goto' function. For the purpose of clarity would it be useful to provide a series of specific test cases (in perl 5) to identify what it does today and what (if anything) it will do differently? Thank you, Tom Allison
Re: S04 default { } bug?
On Mon, Oct 24, 2005 at 07:39:23AM +0300, Ilmari Vacklin wrote: : Hi, : : S04 says thus: : : The default case: : : default {...} : : is exactly equivalent to : : when true {...} : : However, that parses to: : : if $_ ~~ bool::true { ...; leave } : : Which is not executed if $_ is false, unless ~~ bool::true does : something special. It did do something special at the time the Apocalypse was written, but it was probably a bad idea. Smart match was going to recognize obviously boolean expressions and just ignore the other argument. The problem is that it's not always obvious what's obvious. Larry
Re: S04 default { } bug?
On 10/23/05, Ilmari Vacklin <[EMAIL PROTECTED]> wrote: > Hi, > > S04 says thus: > > The default case: > > default {...} > > is exactly equivalent to > > when true {...} > > However, that parses to: > > if $_ ~~ bool::true { ...; leave } > > Which is not executed if $_ is false, unless ~~ bool::true does > something special. Good catch. Given the discussions about given arglist pattern matching, we may be able to make it: when :(_) {...} Or: when -> _ {...} And if not that, then this ought to work: when ({ 1 }) {...} (A nullary codeblock that is evaluated for truth). Luke
S04 default { } bug?
Hi, S04 says thus: The default case: default {...} is exactly equivalent to when true {...} However, that parses to: if $_ ~~ bool::true { ...; leave } Which is not executed if $_ is false, unless ~~ bool::true does something special. Perhaps default should be equivalent to: when $_ { ... } That is, $_ is always $_, so the block is always executed. (It also strikes me that using booleans in when clauses could/should be disallowed entirely.) -- Ilmari Vacklin (wolverian)
Re: PATCH: S04 - unary C<=> is not slurpy
Autrijus asked: On Wed, Jun 15, 2005 at 05:37:18PM -0500, Patrick R. Michaud wrote: Based on an off-list discussion, it turns out that unary C<=> is not slurpy as mentioned in S04. The following patch to S04 corrects this; I've already applied the patch but thought I'd pass it by p6l for review/comments/reactions. Does it mean that it's a synonym to "&readline"? No. It's the general-purpose "iterate this..." operator. Applied to a filehandle, it iterates the filehandle (which *is* equivalent to calling C). But it can also be applied to any other iterator object, in which case it calls that object's C<.next> method. Damian
Re: PATCH: S04 - unary C<=> is not slurpy
On Wed, Jun 15, 2005 at 05:37:18PM -0500, Patrick R. Michaud wrote: > Based on an off-list discussion, it turns out that unary C<=> > is not slurpy as mentioned in S04. The following patch to S04 > corrects this; I've already applied the patch but thought I'd > pass it by p6l for review/comments/reactions. Does it mean that it's a synonym to "&readline"? Thanks, /Autrijus/ pgpGE4T1lI9Ej.pgp Description: PGP signature
PATCH: S04 - unary C<=> is not slurpy
Based on an off-list discussion, it turns out that unary C<=> is not slurpy as mentioned in S04. The following patch to S04 corrects this; I've already applied the patch but thought I'd pass it by p6l for review/comments/reactions. Pm Index: S04.pod === --- S04.pod (revision 3802) +++ S04.pod (working copy) @@ -12,7 +12,7 @@ Maintainer: Larry Wall <[EMAIL PROTECTED]> Date: 19 Aug 2004 - Last Modified: 29 Jan 2005 + Last Modified: 15 Jun 2005 Number: 4 Version: 5 @@ -185,13 +185,10 @@ This has the added benefit of limiting the scope of the C<$line> parameter to the block it's bound to. (The C's declaration of C<$line> continues to be visible past the end of the block. Remember, -no implicit block scopes.) It is possible to write +no implicit block scopes.) It is also possible to write while =$*IN -> $line {...} -But it won't do what you expect, because unary C<=> does a slurp in scalar -context, so C<$line> will contain the entire file. - Note also that Perl 5's special rule causing while (<>) {...}
Re: S04 -- closure traits clarification
On Mon, May 02, 2005 at 03:20:03PM -0700, Larry Wall wrote: : Probably does something like: : : &?BLOCK does First; # no-op if it already does First : &?BLOCK.firstlist.push(&block); Probably shouldn't use up a normal name like "First" for that. Maybe we can just reuse the trait name as the role name &?BLOCK does FIRST; # no-op if it already does First &?BLOCK.FIRST.push(&block); In this view, whether setting a trait clobbers an existing property or merely appends to it depends on the trait handler's implementation. I'm inclining more toward the view that all these blocks are pushed onto the FIRST property at BEGIN time, but the "will first" properties are wrapped in code that prevents them from running before their variable is declared. (Or maybe the wrapper just checks to see if the variable is defined? That would disable the block when you undef the variable. That might be construed as a feature.) Larry
Re: S04 -- closure traits clarification
On Fri, Apr 29, 2005 at 10:57:01AM -0500, David Christensen wrote: : 1) What type of introspection, if any, are we providing to the language : level? I.e., are we providing something along the lines of : : %traits = &?BLOCK.traits : : where %traits is keyed on trait name (FIRST, LAST, whatever) and in : turn is an array of closures? This would mean, for instance that we : could say : : &?BLOCK.traits : : to get the current block's FIRST closures, if any. There is no .traits method. Traits store their values into properties, and properties are just mixins, and you get at the properties by calling methods. These particular traits push onto a correspondingly named property, so you're probably looking for $?BLOCK.firstlist or some such. : When parsing the : block for traits, coming across a new FIRST block would be akin to : saying: : : push &?BLOCK.traits, {...block contents...} : : Specifically, I'm looking for definition of the syntax, which is only : alluded to in the Synopsis. Probably does something like: &?BLOCK does First; # no-op if it already does First &?BLOCK.firstlist.push(&block); : 2) If we accept the introspection at the block-level above, it seems : clear that we should also accept the same .traits method on variables. : I.e., in the above DBI example, we should get back the closure(s) for : undoing by referring to $sth.traits. Is a variable-level trait a : single entry, or can we have multiple "will undo {...}" predicates on a : single variable? (The utility of such is left as an exercise to the : reader.) The variable might not be aware that it has had such a trait applied to it. Remember that traits are allowed to cheat. These traits need only arrange to have &block pushed onto the appropriate list after the corresponding variable is successfully elaborated at run time, or otherwise arrange not to run if their variable is not yet elaborated. If this information also shows up as metadata on the variable, that's probably okay, but the implementation is unlikely to use that property directly. Of course, a trait like "constant" would be expected to an effect on the variable itself. : 3) User-definable traits. Now, this may be a closed domain of sorts, : but do we need to allow for the possibility of user-defined traits? : (I'm thinking here of variable-level "will" predicates.) If so, do : user-defined traits get normalized to UPPER? It would seem like we : would want consistency here, because if "will undo {...}" and "UNDO : {...}" get stored in the same trait slot, we're obviously transforming : one of the identifiers -- should this behavior be specific to our : "built-in" ones, or to all traits? Already specced in A12. As far as I know that part hasn't changed significantly, but that could be because nobody's tried to implement it yet. :-) : 4) Which of the closure traits are supported as "will" predicates on : variables? Not all of the closure traits make sense on the : variable-level -- this information will be useful when trying to parse : the "will" predicates. As Luke mentioned, "will" is just syntactic sugar for "is". A trait is allowed to care about its semantics at compile time when you call the trait handler, but this is totally transparent to the parser, which will happily accept "will qufklzuxfvklj {...}", turn it into "is qufklzuxfvklj({...})", and then fail to find an appropriate trait handler in semantic analysis, or find some default trait handler that scratches its head over "qufklzuxfvklj" before admitting defeat. Or it may be that any trait that is unrecognized just gets applied as a property of the variable. But I think it's better if we treat traits as declared items so that we catch typos, unless someone has explicitly declared a autoloading trait handler. Larry
Re: S04 -- closure traits clarification
David Christensen writes: > Greetings, > > In trying to hack closure trait support into pugs, I have some > questions about closure traits, variable with "will" traits and > introspection. (Apologies if some of this has been discussed on the > list before -- I'm just going off of the synopses, which if definite > clarification on some of these issues has been made, should probably be > updated to reflect the decisions made.) > > Firstly, it is suggested in S04 that variables indicated with a "will" > predicate contribute to the corresponding block-level trait. Not really. `will` is just defined as: $a will foo {...} Is the same as: $a is foo({...}) So it's up to foo to associate itself with the block. > I.e., if we have the following bit of code: > > if $dbh { > my $sth will undo {$dbh.rollback} will keep {$dbh.commit} = FIRST > {$dbh.prepare($query)}; > UNDO { > say "DB error!"; > } > KEEP { > say "We're good!"; > } > } > > Then the block has in effect 5 total traits, 2 UNDO block, 2 KEEP > blocks and 1 FIRST blocks. From what I understand, the blocks for each > trait are executed in FIFO order, thus we would rollback before we > report the error in this contrived example. Nope. Entry-time blocks are executed in declaration order. Exit-time blocks are executed in reverse declaration order. Just like CHECK and END in Perl 5. > Questions: > > 1) What type of introspection, if any, are we providing to the language > level? I.e., are we providing something along the lines of > > %traits = &?BLOCK.traits > > where %traits is keyed on trait name (FIRST, LAST, whatever) and in > turn is an array of closures? This would mean, for instance that we > could say > > &?BLOCK.traits > > to get the current block's FIRST closures, if any. When parsing the > block for traits, coming across a new FIRST block would be akin to > saying: > > push &?BLOCK.traits, {...block contents...} > > Specifically, I'm looking for definition of the syntax, which is only > alluded to in the Synopsis. What you are saying here seems reasonable. However, we have to remember that the closures are different for each run. So the traits are not associated with the block, but with the particular runtime instance of the block. Maybe that's what &?BLOCK refers to anyway. I wonder how you could talk about the traits of a sub that isn't currently executing. > 2) If we accept the introspection at the block-level above, it seems > clear that we should also accept the same .traits method on variables. > I.e., in the above DBI example, we should get back the closure(s) for > undoing by referring to $sth.traits. Is a variable-level trait a > single entry, or can we have multiple "will undo {...}" predicates on a > single variable? (The utility of such is left as an exercise to the > reader.) The question is, are you asking about the variable or the value? For instance: my $block = &?BLOCK; # _not_ calling $block.traits;# variable traits or &?BLOCK traits? We probably just use whatever the equivalent of `tied` is these days. Let's call it, er, `tied`. $block.traits; # &?BLOCK traits (tied $block).traits; # variable traits > 3) User-definable traits. Now, this may be a closed domain of sorts, > but do we need to allow for the possibility of user-defined traits? No. By which I mean OF COURSE! > (I'm thinking here of variable-level "will" predicates.) If so, do > user-defined traits get normalized to UPPER? No. Block level traits are different from variable traits, and they should be declared separately. The variable trait `undo` for instance probably just pushes an UNDO handler on its caller. Likewise, the UNDO macro (?) does precisely the same thing. But people are allowed to declare traits that are all caps, and block handlers which are lowercase, and any combination of the above. Perl culture will try to enforce against that, however. > It would seem like we would want consistency here, because if "will > undo {...}" and "UNDO {...}" get stored in the same trait slot, we're > obviously transforming one of the identifiers -- should this behavior > be specific to our "built-in" ones, or to all traits? > > 4) Which of the closure traits are supported as "will" predicates on > variables? Not all of the closure traits make sense on the > variable-level -- this information will be useful when trying to parse > the "will" predicates. Hmm, not quite sure. Traits are a pretty big thing, and I'm not sure what it buys you to hack them in. I'd start by implementing the block handlers without variable traits. Luke
S04 -- closure traits clarification
Greetings, In trying to hack closure trait support into pugs, I have some questions about closure traits, variable with "will" traits and introspection. (Apologies if some of this has been discussed on the list before -- I'm just going off of the synopses, which if definite clarification on some of these issues has been made, should probably be updated to reflect the decisions made.) Firstly, it is suggested in S04 that variables indicated with a "will" predicate contribute to the corresponding block-level trait. I.e., if we have the following bit of code: if $dbh { my $sth will undo {$dbh.rollback} will keep {$dbh.commit} = FIRST {$dbh.prepare($query)}; UNDO { say "DB error!"; } KEEP { say "We're good!"; } } Then the block has in effect 5 total traits, 2 UNDO block, 2 KEEP blocks and 1 FIRST blocks. From what I understand, the blocks for each trait are executed in FIFO order, thus we would rollback before we report the error in this contrived example. Questions: 1) What type of introspection, if any, are we providing to the language level? I.e., are we providing something along the lines of %traits = &?BLOCK.traits where %traits is keyed on trait name (FIRST, LAST, whatever) and in turn is an array of closures? This would mean, for instance that we could say &?BLOCK.traits to get the current block's FIRST closures, if any. When parsing the block for traits, coming across a new FIRST block would be akin to saying: push &?BLOCK.traits, {...block contents...} Specifically, I'm looking for definition of the syntax, which is only alluded to in the Synopsis. 2) If we accept the introspection at the block-level above, it seems clear that we should also accept the same .traits method on variables. I.e., in the above DBI example, we should get back the closure(s) for undoing by referring to $sth.traits. Is a variable-level trait a single entry, or can we have multiple "will undo {...}" predicates on a single variable? (The utility of such is left as an exercise to the reader.) 3) User-definable traits. Now, this may be a closed domain of sorts, but do we need to allow for the possibility of user-defined traits? (I'm thinking here of variable-level "will" predicates.) If so, do user-defined traits get normalized to UPPER? It would seem like we would want consistency here, because if "will undo {...}" and "UNDO {...}" get stored in the same trait slot, we're obviously transforming one of the identifiers -- should this behavior be specific to our "built-in" ones, or to all traits? 4) Which of the closure traits are supported as "will" predicates on variables? Not all of the closure traits make sense on the variable-level -- this information will be useful when trying to parse the "will" predicates. Thanks, David Christensen
thank you for clarification (was Re: S04)
On Thu, Feb 10, 2005 at 09:45:59AM -0800, Larry Wall wrote: > That's spelled > > loop { > $foo = readline; > ...do stuff with $foo... > } while ( $foo ); > > these days. > > Larry Cool, perfect. Thanks. --Dks -- [EMAIL PROTECTED]
Re: S04
On Thu, 2005-02-10 at 11:59, Luke Palmer wrote: > There's been some discussion about bringing a syntax back for that > recently, but I haven't really been paying attention. Anyway, this is > pretty clear: > > loop { > $foo = readline; > do { stuff :with($foo) }; > last unless $foo; > } Well, yes it's clear, but then you run into the problem where your code looks like: while stuff() { more_stuff(); } loop { other_more_stuff(); last unless other_stuff(); } and then you want to add something like: next if things(); to both... you have to do it in two ways. The Perl 6ish way of dealing with this is: while stuff() { next if things(); more_stuff(); } loop { next if other_things(); other_more_stuff(); NEXT { last unless other_stuff(); } } I think Larry's contention has been that loop is all you really need, and everything else is a macro. If you really want dowhile, then it's something like (making up macro example on the fly, and probably wrong here...): macro infix:dowhile (Code $block, Bool $cond) { loop { $block.(); NEXT { last unless $cond.() } } } { next if other_things(); other_more_stuff(); } dowhile other_stuff(); Of course, that assumes that an expanded macro will, by default, handle the case when you pass it code that invokes a loop control, expecting to control the loop inside the macro first. -- â 781-324-3772 â [EMAIL PROTECTED] â http://www.ajs.com/~ajs
Re: S04
On Thu, Feb 10, 2005 at 07:39:54AM -0800, David Storrs wrote: : Given that Perl 6 won't support an actual do-while loop a la C++ (and : yes, I know that Perl5 didn't either), how would you accomplish that? : That is, I'd like to have a loop that runs once, then checks its : condition to see if it should repeat and continues to repeat as long : as the condition is true. : : I don't think this works, but here's what I'm look for: : : { : $foo = readline; : ...do stuff with $foo... : } while ( $foo ); That's spelled loop { $foo = readline; ...do stuff with $foo... } while ( $foo ); these days. Larry
Re: S04
David Storrs writes: > Given that Perl 6 won't support an actual do-while loop a la C++ (and > yes, I know that Perl5 didn't either), how would you accomplish that? > That is, I'd like to have a loop that runs once, then checks its > condition to see if it should repeat and continues to repeat as long > as the condition is true. > > I don't think this works, but here's what I'm look for: > > { > $foo = readline; > ...do stuff with $foo... > } while ( $foo ); There's been some discussion about bringing a syntax back for that recently, but I haven't really been paying attention. Anyway, this is pretty clear: loop { $foo = readline; do { stuff :with($foo) }; last unless $foo; } Luke
Re: S04
Given that Perl 6 won't support an actual do-while loop a la C++ (and yes, I know that Perl5 didn't either), how would you accomplish that? That is, I'd like to have a loop that runs once, then checks its condition to see if it should repeat and continues to repeat as long as the condition is true. I don't think this works, but here's what I'm look for: { $foo = readline; ...do stuff with $foo... } while ( $foo ); --Dks
Re: S04
Thank you for your fast and detailed reply. Larry Wall skribis 2005-01-29 11:08 (-0800): > On Sat, Jan 29, 2005 at 05:59:40PM +0100, Juerd wrote: > : Can last/redo be used outside loops? (i.e. with if or given) > No, though of course what "loop" means is negotiable. Effectively, > anything that captures the appropriate control exceptions is a loop. redo could be useful in subs or even file scope. CATCH { when Fatal { reset; redo; } } And in given, for those who don't like fall-through: GIVEN: given $foo { when /^0x/ { $_.=hex; redo GIVEN; } ... } # Heh, I guess here $_.=hex, $_=hex and $_=.hex all do the same # thing :) > So there's some argument for keeping bare {...} as a do-once loop. > (..) But this morning it occurs > to me that if we defined C to be a do-once loop, it kind of > naturally rules out putting an C or C modifier on it, > since you then have conflicting loop specifications. It also kind of naturally rules out that do { } is for grouping statements in an expression, because it'd behave *very* differently in void context. And wasn't Perl 6 supposed to weed out weird exceptions? :) $foo = %*ENV; $foo = do { print "Foo: "; readline } until $foo.validate; # valid do { print "Foo: "; $foo = readline } until $foo.validate; # invalid? Maybe it doesn't hurt to tell people who need a once-loop to just use loop with last: loop { ... last; } Those who find comfort in knowing beforehand that it'll only run once, can use NEXT { last } :) Juerd
Re: S04
On Sat, Jan 29, 2005 at 05:59:40PM +0100, Juerd wrote: : Some questions after reading S04: : : : Can last/redo be used outside loops? (i.e. with if or given) No, though of course what "loop" means is negotiable. Effectively, anything that captures the appropriate control exceptions is a loop. But I think the design is best served if it's pretty well known what an "official" loop is, much as we say what an official "sub" is so that we know which entity is exited when you say "return". To that end, the control exceptions for next/last/redo may well include information on which outer lexical scope is intended, presuming there's a surrounding lexical scope that is the obvious target. The p5-ish behavior of scanning out the dynamic scopes for an appropriate label would perhaps be a fallback if there is no appropriate lexical scope. In other words, if you say "next METHOD", and there's a METHOD: label in your current sub, we should probably assume the user means that METHOD label rather than the METHOD label on the implicit method dispatcher. : Is a bare block still a loop? We need a do-once loop. Or if we don't exactly need it, it certainly turned out to be handy in Perl 5, if only to provide a switch statement. I think it would be surprising, though, to turn C into a loop. Plus, it has other difficulties as a do-once loop. It requires an argument before the closure, and it clobbers $_. C suffers similarly. So there's some argument for keeping bare {...} as a do-once loop. It doesn't suffer the argument problems of C, though it does suffer from a bit surprising to newcomers. But this morning it occurs to me that if we defined C to be a do-once loop, it kind of naturally rules out putting an C or C modifier on it, since you then have conflicting loop specifications. I realize that's just a rationalization, since you could certainly define it such that the do {...} nested inside the statement modifier. But I'm looking at it more from a psychological-space viewpoint here, and since we're outlawing do-while anyway, we might as well give people a semilogical reason for it, which they can take as a semological reason if they like. But speaking of semology, another psychological argument in favor of that is that the longer construct should have more semantics than the shorter one. That is, the marked form should do more than the unmarked form. Plus the simple fact that introducing loop semantics into bare blocks at the same time as making all blocks closures potentially introduces halting-problem-ish non-optimizabilities--how can we know that the bare block isn't going to execute a "next" someplace in it. So for the moment, let's say that bare block is not a loop, but a C block is. It might provide some short-term confusion to Perl 5 programmers, but I think the risk is worth it, unless someone can spot additional difficulties. : Can loop be used as a statement modifier? (say 'y' loop;) Seems awfully obscure just to save two curlies, and I'm not sure the fact that something is an infinite loop can ever be construed as unimportant enough to be relegated to the right margin. : Can OUTER be stacked? ($OUTER::OUTER::_) Yep. You'll note it's not a subtle construct--this is quite intentional. : TIA. YWIR. Larry
S04
Some questions after reading S04: Can last/redo be used outside loops? (i.e. with if or given) Is a bare block still a loop? Can loop be used as a statement modifier? (say 'y' loop;) Can OUTER be stacked? ($OUTER::OUTER::_) TIA. Juerd