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
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.
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 ;-)
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
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?
(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 :/