Re: [A-Z]+\s*\{
Larry Wall [EMAIL PROTECTED] writes: [EMAIL PROTECTED] writes: [...] : How does one enforce the no side-effects rule, and how deeply does it : traverse? Dunno. Could warn or fail on assignment to any non-lexical or non-local lexical as a start. Maybe we could warn or fail on method calls known to modify an object. But I don't know how much technological enforcement we can achieve without an unnecessarily fascist declaration policy. I expect the most important thing would be to encourage people to think that way. You cannot usefully tell if something has a side effect. Well, you can do stuff like warn if it obviously contains assignments, prints and maybe gotos, or you can run it and die horribly if it tries to do one of the above. But I doubt this would be useful. Here's an example. Suppose f is a function with no side effects. Then I can write POST { f($x) == $y or die; # (die is the ultimate side effect, but # it's somehow still OK, right?) } Now, since f is a function with no side effects, I can Memoize it a la MJD, right? But I can't do both at once, because then my POST will call the Memoize'd f, which has what is technically a side effect. How about POST { %h{$x} == $y or die; } OK, right? And if %h is really tie'd to a file? The point is that what counts as a real side effect depends on the program, not on the language. (Well, maybe not if you're a functional programmer). The definition is that an expression has side effects if it can affect the (internal or external) state of the program. But the *useful* definition is that an expression has side effects if it can affect the state of the program in a manner which matters to the program. I'd say warn in the documentation that PRE and POST should not contain side effects, maybe even add a switch to disable their execution, but not attempt to enforce anything. It's just not useful, I think. [...] : sub non_method { : loop { : PRE { : print PRE\n; # Is printing a side-effect? Gee, maybe warnings and failures are side effects, and should be also prohibited. :-) print is OK (for a program running on the console STDOUT not usefully redirected, etc.), because its side effect presumably doesn't matter to the program. In a CGI application, print would not be side effect free. Like I said earlier, I think the important thing is to make people think about it, not to continually frustrate them. I'd be inclined to let people choose their own level of pain by setting DbC strictness thresholds. Please set my threshold of side effect pain to undef... -- Ariel Scolnicov|http://3w.compugen.co.il/~ariels Compugen Ltd. |[EMAIL PROTECTED] 72 Pinhas Rosen St.|Tel: +972-3-7658117 fast, good, and cheap; Tel-Aviv 69512, ISRAEL |Fax: +972-3-7658555 pick any two!
Re: [A-Z]+\s*\{
Larry wrote: : One way to do that would be to define POST and NEXT to return their : own (single, closure) argument. So then you could write: : : NEXT POST { ... } As long as everyone realizes that that return happens at compile time... Sorry, yes, I should have been explicit about that. Damian
Re: [A-Z]+\s*\{
Larry Wall writes: : This is only slightly less problematic than : : NEXT $coderef; : : which in turn is only slightly less problematic than : : if $condition $coderef; Actually, that'd probably have to be: if $condition, $coderef; Still not sure if that has any possibility of actually working. Maybe depends on how the regex for the Cif syntax is written, and whether such syntax can fall back onto ordinary syntactic conventions. Probably not. Something tells me that we'd better require the block of Cif et al., or we'll have difficulty detecting missing semicolons, which would try to make an Cif statement parse as an Cif modifier. This has slightly more chance of working: $condition.if($ifcode, $elsecode) But really, people will be surprised if you do that. They'll expect you to write this instead: $condition ?? $ifcode() :: $elsecode(); So I'm not terribly interested in going out of my way to make statement blocks parse exactly like terms in an ordinary expressions. If it happens, it'll probably be by accident. Larry
Re: [A-Z]+\s*\{
On Monday 21 January 2002 11:14, Larry Wall wrote: So I'm not terribly interested in going out of my way to make statement blocks parse exactly like terms in an ordinary expressions. If it happens, it'll probably be by accident. That's fine. (And I agree.) All I really cared about was map, grep, and sort. The rest was was simply an extension to the implausable end. -- Bryan C. Warnock [EMAIL PROTECTED]
Re: [A-Z]+\s*\{
On Sun 20 Jan, Me wrote: On Saturday 19 January 2002 22:05, Brent Dax wrote: Is this list of special blocks complete and correct? BEGIN Executes at the beginning of compilation CHECK Executes at the end of compilation INIT Executes at the beginning of run END Executes at the end of run PRE Executes at beginning of block entry POST Executes at end of block entry NEXT Executes on call to next() within current block CATCH Executes on exception within current block KEEP Executes on normal exit of the current block UNDO Executes on un-normal exit of the current block - LAST (Per Damian's last (LAST/POST) post.) - FIRST? (Symmetry.) - ALWAYS? (Another plausible addition. Rounds out PRE and POST with invariant assertions that get checked twice, once at the time PRE does, once at the time POST does. Personally I'd leave this out until it became clear, well past p6.0, whether it was really worth it, but it seems worth mentioning.). To complete such a list perhaps there is a case for: NEVER :-) Richard -- Personal Work - Waveney Consulting Mail: [EMAIL PROTECTED] [EMAIL PROTECTED] Web: http://www.waveney.org http://www.WaveneyConsulting.com Independent Telecommunications Consultant, ATM expert, Web Analyst
Re: [A-Z]+\s*\{
On Saturday 19 January 2002 22:05, Brent Dax wrote: Is this list of special blocks complete and correct? Close and close. As of two days ago, Larry's thinking was: BEGIN Executes at the beginning of compilation CHECK Executes at the end of compilation INITExecutes at the beginning of run END Executes at the end of run PRE Executes at block entry. Inherited if block is a method. No side-effects allowed. POSTExecutes at block exit. Inherited if block is a method. No side-effects allowed. NEXTExecutes on (explicit or implicit) call to next() within current block CATCH Executes on exception within current block LASTExecutes on any form of block exit. Not inherited (c.f. POST), even if block is a method. Side-effects allowed. KEEPSpecialized form of CATCH. Executes on control exception in the current block UNDOSpecialized form of CATCH. Executes on non-control exception in the current block Damian
Re: [A-Z]+\s*\{
On Sun, 20 January 2002, Me wrote - LAST (Per Damian's last (LAST/POST) post.) Yup. - FIRST? (Symmetry.) No. We feel that such code just goes at the start of the block. Of course, there's an argument that you might have several entry points to a block (via Cgoto labels) and still want some code executed no matter where you land inside. I'm just not sure we really want to support that pathology. ;-) - ALWAYS? (Another plausible addition. Rounds out PRE and POST with invariant assertions that get checked twice, once at the time PRE does, once at the time POST does. Personally I'd leave this out until it became clear, well past p6.0, whether it was really worth it, but it seems worth mentioning.). I feel the same way. Invariant checking in most Design-by-Contract systems doesn't work that way, and has another purpose entirely. Invariants are implicitly POST blocks that are automatically distributed to *all* methods of the class for which they're defined, but which only execute on transitions back to callers *outside* that class's hierarchy. Perl 6 *will* have invariant checking, but I believe it should be via a property on the class declaration: class Positive is always { $.value 0 } is always { $.feelings =~ /optimistic/i } is always { $.polarity eq '+' }; Damian
Re: [A-Z]+\s*\{
On Sunday 20 January 2002 08:29, [EMAIL PROTECTED] wrote: On Saturday 19 January 2002 22:05, Brent Dax wrote: Is this list of special blocks complete and correct? Close and close. As of two days ago, Larry's thinking was: Note to self: Program flow BEGIN Executes at the beginning of compilation CHECK Executes at the end of compilation INITExecutes at the beginning of run END Executes at the end of run Note to self: Block flow PRE Executes at block entry. Inherited if block is a method. No side-effects allowed. POSTExecutes at block exit. Inherited if block is a method. No side-effects allowed. NEXTExecutes on (explicit or implicit) call to next() within current block CATCH Executes on exception within current block LASTExecutes on any form of block exit. Not inherited (c.f. POST), even if block is a method. Side-effects allowed. KEEPSpecialized form of CATCH. Executes on control exception in the current block UNDOSpecialized form of CATCH. Executes on non-control exception in the current block Is it POST, LAST or LAST, POST, at runtime? How does one enforce the no side-effects rule, and how deeply does it traverse? Do I remember right that 'return' creates a control exception? Do KEEP and UNDO take the place of CATCH within a block? (ie, you may either CATCH, or you may KEEP and UNDO, but not both?) If all three are allowed, what is the exception handling order? Which blocks may you have more than one of within the same block, and in what order will they execute? In one cannot (or does not) inherit a PRE, POST, or LAST block, is there a way to add one without recreating the entire block. When you say inheritence (which implies a sub), not inheriting only applies to the outer-most scope - the sub scope - currect? Any container blocks should still have their full semantics preserved, so that an embedded while block, for instance, would still have its corresponding LAST, I hope. If that were the case, could you then get around the inheritence issue by enclosing the entire body of the sub inside its own block? (I'm not saying that that's a good idea, just asking whether it could be done.) sub non_method { loop { PRE { print PRE\n; # Is printing a side-effect? ... } POST { print POST\n; ... } LAST { print LAST\n; ... } code(); last; } } -- Bryan C. Warnock [EMAIL PROTECTED]
Re: [A-Z]+\s*\{
On Sun, Jan 20, 2002 at 05:29:39AM -0800, Damian Conway wrote: On Saturday 19 January 2002 22:05, Brent Dax wrote: Is this list of special blocks complete and correct? Close and close. As of two days ago, Larry's thinking was: BEGIN Executes at the beginning of compilation CHECK Executes at the end of compilation INITExecutes at the beginning of run END Executes at the end of run PRE Executes at block entry. Inherited if block is a method. No side-effects allowed. POSTExecutes at block exit. Inherited if block is a method. No side-effects allowed. NEXTExecutes on (explicit or implicit) call to next() within current block If a POST is inside a loop, is it executed at the end of each iteration or only when the loop exits ? If it is only when the loop exits, will it be possible to designate a block to be multiple (eg both POST and NEXT) Graham. CATCH Executes on exception within current block LASTExecutes on any form of block exit. Not inherited (c.f. POST), even if block is a method. Side-effects allowed. KEEPSpecialized form of CATCH. Executes on control exception in the current block UNDOSpecialized form of CATCH. Executes on non-control exception in the current block Damian
Re: [A-Z]+\s*\{
Bryan C. Warnock wrote: Is it POST, LAST or LAST, POST, at runtime? Since POST is checking invariants, and LAST can have side effects, LAST must be executed before POST. Apo 4 said POSTs were executed in the reverse of the order seen, I presume that would hold for LAST as well. How does one enforce the no side-effects rule, and how deeply does it traverse? Good question! Do I remember right that 'return' creates a control exception? Yes. Do KEEP and UNDO take the place of CATCH within a block? (ie, you may either CATCH, or you may KEEP and UNDO, but not both?) If all three are allowed, what is the exception handling order? The way I hear it, KEEP/UNDO get executed if there are control/other exceptions raised, but they do not themselves catch exceptions. The ordering will be interesting to learn... I'd think/hope KEEP or UNDO would be executed before CATCH. Which blocks may you have more than one of within the same block, and in what order will they execute? It would be nice to have the chart... Here's my interpretation, corrections welcomed from those in the know. I see no reason not to permit multiple instances of any of the types of blocks, although they could be restricted as unnecessary (especially those marked yes?. It seems there might not be much reason to allow multiples of those, but unless there is an implementation reason not to, why not?) block side multiple order type effects instances PREno yes?/order seenbefore regular code in block inherited before locally defined regular code yes n/aafter PRE, until exception KEEP yes yes/reverse order if control exception, ofter reg UNDO yes yes/reverse order if non-control exception, after reg CATCH yes yes?/order seenafter KEEP/UNDO until exception is cleaned LAST yes yes/reverse order after regular code if no exception after CATCH if exception POST no yes?/reverse order after LAST locally defined before inherited In one cannot (or does not) inherit a PRE, POST, or LAST block, is there a way to add one without recreating the entire block. Seems like you could always have your own blocks of any kind... just define them. In addition, you might inherit one from somewhere else. -- Glenn = Due to the current economic situation, the light at the end of the tunnel will be turned off until further notice.
Re: [A-Z]+\s*\{
[EMAIL PROTECTED] writes: : Is it POST, LAST or LAST, POST, at runtime? Obviously you want to put the assertion checking after the cleanup, so LAST, POST. : How does one enforce the no side-effects rule, and how deeply does it : traverse? Dunno. Could warn or fail on assignment to any non-lexical or non-local lexical as a start. Maybe we could warn or fail on method calls known to modify an object. But I don't know how much technological enforcement we can achieve without an unnecessarily fascist declaration policy. I expect the most important thing would be to encourage people to think that way. : Do I remember right that 'return' creates a control exception? Yes, unless it can be optimized to a goto. : Do KEEP and UNDO take the place of CATCH within a block? (ie, you may either : CATCH, or you may KEEP and UNDO, but not both?) If all three are allowed, : what is the exception handling order? I think of KEEP and UNDO as LAST blocks, not CATCH blocks, because there can only be one CATCH block, but there can be multiple LAST blocks. They just happen to have secret knowledge of whether the block was successful or not. How that interacts with a previously occurring CATCH is still a little up in the air. I suppose it should be possible for a CATCH to signal success even though a fatal exception was caught. I wouldn't think that would be the default, though. Maybe it has to wipe out $! manually or change $! to an innocuous exception type for the KEEPs to run instead of the UNDOs. : Which blocks may you have more than one of within the same block, and in : what order will they execute? As far as I know, only CATCH is limited to one, and the basic principle for order is that things that run at the beginning of something run in forward order, while things that run at the end run in reverse order. : In one cannot (or does not) inherit a PRE, POST, or LAST block, is there a : way to add one without recreating the entire block. I expect PRE and POST could inherit automatically according to the usual rules of DbC, though how you implement that is something other people have thought about more than me. I think that LAST doesn't inherit. If you want to share common code, there's this neat Perl 6 invention called subroutines you can use. : When you say inheritence (which implies a sub), not inheriting only applies : to the outer-most scope - the sub scope - currect? Any container blocks : should still have their full semantics preserved, so that an embedded while : block, for instance, would still have its corresponding LAST, I hope. Yes. : If that were the case, could you then get around the inheritence issue by : enclosing the entire body of the sub inside its own block? (I'm not saying : that that's a good idea, just asking whether it could be done.) Yes. : sub non_method { : loop { : PRE { : print PRE\n; # Is printing a side-effect? Gee, maybe warnings and failures are side effects, and should be also prohibited. :-) Like I said earlier, I think the important thing is to make people think about it, not to continually frustrate them. I'd be inclined to let people choose their own level of pain by setting DbC strictness thresholds. Larry
Re: [A-Z]+\s*\{
On Sunday 20 January 2002 20:57, Larry Wall wrote: I expect PRE and POST could inherit automatically according to the usual rules of DbC, though how you implement that is something other people have thought about more than me. I think that LAST doesn't inherit. If you want to share common code, there's this neat Perl 6 invention called subroutines you can use. Funny you should say that. The question I hadn't asked yet: Since these blocks are all closures now, will the different methods for passing code blocks be interchangeable (or simplified)? User code code can pass '{ ... }' if a sub's prototype wants a coderef, to better match map and grep; sort can take a bare block or the name of a sub, but none of the three can take a reference to a sub. Whereas this mostly makes (made) sense, can code truly start being interchangable? Can I write reusable transformers and filters for map and grep, simply passing in a ref to the proper routine rather than the code block? How would this interact (or react) with curried code blocks? If this is a good first step, how far can it extend? Could I write a sub, and pass a reference to it directly to LAST, for instance: LAST $coderef; or would I simply wrap it? LAST { $coderef; } -- Bryan C. Warnock [EMAIL PROTECTED]
Re: [A-Z]+\s*\{
At 5:57 PM -0800 1/20/02, Larry Wall wrote: [EMAIL PROTECTED] writes: : How does one enforce the no side-effects rule, and how deeply does it : traverse? Dunno. Could warn or fail on assignment to any non-lexical or non-local lexical as a start. Maybe we could warn or fail on method calls known to modify an object. But I don't know how much technological enforcement we can achieve without an unnecessarily fascist declaration policy. I expect the most important thing would be to encourage people to think that way. Anything like that I can see being reasonably expensive to provide in the runtime. I'm not sure if it can be done without cost in all circumstances either. (We'd need to trap all write access, and I can't imagine that being cheap. I admit I'd rather not have to imagine a way that it was... :) -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: [A-Z]+\s*\{
Bryan C. Warnock asked: Is it POST, LAST or LAST, POST, at runtime? LAST then POST I suspect. For reasons already given in someone else's reply. But, just possibly: intermixed in reverse order of definition. How does one enforce the no side-effects rule, and how deeply does it traverse? By prohibiting mutation of variables not lexical to the block, forbidding I/O, allowing calls only to already-defined subs, and applying the same restrictions recursively to those subs. Do I remember right that 'return' creates a control exception? Yes. Do KEEP and UNDO take the place of CATCH within a block? (ie, you may either CATCH, or you may KEEP and UNDO, but not both? Correct. KEEP+UNDO = CATCH and you can only have one CATCH per block. If one cannot (or does not) inherit a PRE, POST, or LAST block, LAST blocks aren't ever inherited. is there a way to add one without recreating the entire block. Probably not. If there were, it would be via the block's MY pseudoclass and be subject to the same compile-time modifications only constraints as other up-scope lexical manipulations. When you say inheritence (which implies a sub) implies a method. Not the same thing in Perl 6. not inheriting only applies to the outer-most scope - the sub scope - currect? Any container blocks should still have their full semantics preserved, so that an embedded while block, for instance, would still have its corresponding LAST Of course. If that were the case, could you then get around the inheritence issue by enclosing the entire body of the sub inside its own block? (I'm not saying that that's a good idea, just asking whether it could be done.) Err. I'm afraid you lost me there. What are you trying to achieve, again? sub non_method { loop { PRE { print PRE\n; # Is printing a side-effect? ... } Printing can be a side effect. For example, your example modifies a global filehandle. Damian
Re: [A-Z]+\s*\{
Graham Barr wrote: If a POST is inside a loop, is it executed at the end of each iteration or only when the loop exits ? Only on final exit. If it is only when the loop exits, will it be possible to designate a block to be multiple (eg both POST and NEXT) One way to do that would be to define POST and NEXT to return their own (single, closure) argument. So then you could write: NEXT POST { ... } Damian
Re: [A-Z]+\s*\{
Damian Conway wrote (apparently whilst on stupid pills): Do KEEP and UNDO take the place of CATCH within a block? (ie, you may either CATCH, or you may KEEP and UNDO, but not both? Correct. KEEP+UNDO = CATCH and you can only have one CATCH per block. As Larry has already pointed out: KEEP + UNDO = LAST, not CATCH. Hence you can have as many of them as you need. Nurse! It must be time for my medication! %-) Damian
Re: [A-Z]+\s*\{
[EMAIL PROTECTED] writes: : On Sunday 20 January 2002 20:57, Larry Wall wrote: : I expect PRE and POST could inherit automatically according to the : usual rules of DbC, though how you implement that is something other : people have thought about more than me. I think that LAST doesn't : inherit. If you want to share common code, there's this neat Perl 6 : invention called subroutines you can use. : : Funny you should say that. The question I hadn't asked yet: : : Since these blocks are all closures now, will the different methods for : passing code blocks be interchangeable (or simplified)? I don't think we can completely simplify it. The following two are certainly interchangeable: - $a, $b { $a = $b } { $^a = $^b } except that the first one can do things like: - $a is rw, $b { $a = $b } while the second automatically does currying. Certainly your good old-fashioned sub ($a is rw, $b) { $a = $b } can be used anywhere a CODE pointer is expected at runtime. I don't know if I like for @foo sub ($x) { ... } but it could be made to work, provided we force Csub to start a term as we've done with - and left curly. I don't feel greatly motivated to do that, however. : User code code can pass '{ ... }' if a sub's prototype wants a coderef, to : better match map and grep; sort can take a bare block or the name of a sub, : but none of the three can take a reference to a sub. Whereas this mostly : makes (made) sense, can code truly start being interchangable? Can I write : reusable transformers and filters for map and grep, simply passing in a ref : to the proper routine rather than the code block? How would this interact : (or react) with curried code blocks? I don't know how far we can push it. Certainly it would be really weird to expect BEGIN $code; to work unless their were an earlier BEGIN that happened to set $code. But if BEGIN has a prototype of (), perhaps it's just parsed as a unary operator and that just works. On the other hand, that's not how the first argument of grep $_, @foo currently works in Perl 5. In that case, the first argument is being forced to be treated as if it were curried: grep $^a, @foo But that means that $_ can't contain a sub reference! I suspect that we have to outlaw forms of grep in which $_ auto-curries itself if we want grep $somesub, @foo To be the same as grep { $somesub() } @foo I think it's fair to trade auto-currying of $_ for that flexibility. : If this is a good first step, how far can it extend? Could I write a sub, : and pass a reference to it directly to LAST, for instance: : : LAST $coderef; : : or would I simply wrap it? : : LAST { : $coderef; : } Well, a wrapper will always work, except that's not how you'd write it in Perl 6. The doesn't call the sub, the parens do. So you'd have to say LAST { $coderef(); } What I can't figure out is, when you write LAST $coderef; when would it actually do the %MY._LAST_list.push($coderef)? Unfortunately, I think it has to do it at compile time, or we can't guarantee that the LAST actually gets run if an exception is thrown early. And in that case, $coderef is likely not set yet. This seems like a recipe for confusion, if not disaster. At the end of the day, I suspect [A-Z]+ blocks will really want to be literal blocks because we want to do various sorts of analysis of them at compile time. We wouldn't be able to tell at compile time if POST $coderef; does any horrible side effects, for instance, unless we guarantee that $coderef is defined when the POST is compiled. I think we'd often have people trying to write things like: my $coderef = sub { ... }; LAST $coderef; and then wondering why it says Undefined LAST block or some such. Larry
Re: [A-Z]+\s*\{
Damian Conway writes: : Graham Barr wrote: : : If a POST is inside a loop, is it executed at the end of each : iteration or only when the loop exits ? : : Only on final exit. : : If it is only when the loop exits, will it be possible to designate : a block to be multiple (eg both POST and NEXT) : : One way to do that would be to define POST and NEXT to return their own : (single, closure) argument. So then you could write: : : NEXT POST { ... } As long as everyone realizes that that return happens at compile time... This is only slightly less problematic than NEXT $coderef; which in turn is only slightly less problematic than if $condition $coderef; Ick. Larry
Re: [A-Z]+\s*\{
Brent Dax writes: : Larry Wall: : # I think we'd often : # have people trying to write things like: : # : # my $coderef = sub { ... }; : # LAST $coderef; : # : # and then wondering why it says Undefined LAST block or some such. : : Maybe all of the [A-Z]+'s get defined each time the block is entered : (or, if the block is being iterated on, the first time the block is : entered during this set of iterations). That would still leave $coderef undefined in the above snippet. Larry
[A-Z]+\s*\{
Is this list of special blocks complete and correct? BEGIN Executes at the beginning of compilation CHECK Executes at the end of compilation INITExecutes at the beginning of run END Executes at the end of run PRE Executes at beginning of block entry POSTExecutes at end of block entry NEXTExecutes on call to next() within current block CATCH Executes on exception within current block KEEPExecutes on normal exit of the current block UNDOExecutes on un-normal exit of the current block --Brent Dax [EMAIL PROTECTED] Parrot Configure pumpking and regex hacker obra . hawt sysadmin chx0rs lathos This is sad. I know of *a* hawt sysamin chx0r. obra I know more than a few. lathos obra: There are two? Are you sure it's not the same one?
Re: [A-Z]+\s*\{
On Saturday 19 January 2002 22:05, Brent Dax wrote: Is this list of special blocks complete and correct? BEGIN Executes at the beginning of compilation CHECK Executes at the end of compilation INITExecutes at the beginning of run END Executes at the end of run PRE Executes at beginning of block entry POSTExecutes at end of block entry NEXTExecutes on call to next() within current block CATCH Executes on exception within current block KEEPExecutes on normal exit of the current block UNDOExecutes on un-normal exit of the current block That matches my list. -- Bryan C. Warnock [EMAIL PROTECTED]
Re: [A-Z]+\s*\{
On Saturday 19 January 2002 22:05, Brent Dax wrote: Is this list of special blocks complete and correct? BEGIN Executes at the beginning of compilation CHECK Executes at the end of compilation INIT Executes at the beginning of run END Executes at the end of run PRE Executes at beginning of block entry POST Executes at end of block entry NEXT Executes on call to next() within current block CATCH Executes on exception within current block KEEP Executes on normal exit of the current block UNDO Executes on un-normal exit of the current block - LAST (Per Damian's last (LAST/POST) post.) - FIRST? (Symmetry.) - ALWAYS? (Another plausible addition. Rounds out PRE and POST with invariant assertions that get checked twice, once at the time PRE does, once at the time POST does. Personally I'd leave this out until it became clear, well past p6.0, whether it was really worth it, but it seems worth mentioning.). --me