$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] [Boost.Breakable] Any interest in a Boost Breakable library?
From: OvermindDL1 (overminddl1_at_[hidden])
Date: 2009-09-07 04:44:26
On Mon, Sep 7, 2009 at 1:40 AM, Gottlob Frege<gottlobfrege_at_[hidden]> wrote:
> On Mon, Sep 7, 2009 at 2:14 AM, Pierre
> Morcello<pmorcell-cppfrance_at_[hidden]> wrote:
>> Thanks Michael, I did not think sooner to the 'else if'. But there is one problem with the 'else if' : you can not do calculations between the tests.
>>
>> When I work often my code looks like :
> ...
>
> Another 'lifer' here (20+ years!) :-)
>
> I think, by now, we all know and have seen the type of code you are
> talking about. Â I saw it a lot with Windows GUI programming - get the
> HWND, check, Get the DC, check, do some stuff, make a HPEN, check,...
>
> I have yet to see a perfect solution. Â Some of the solutions I've seen:
>
> 1) try to do all the checks at the top:
>
> void func(P1 p1, P2 p2, ...)
> {
> Â if (!IsOK(p1)) return;
> Â if (!IsOK(p2)) return;
> Â etc
>
> Â now do stuff...
> }
>
> I think this is pretty good if all the checks are just checking
> inputs. Â but it gets hairy in those cases, as mentioned, when there is
> other code in between. Â An alternative to this is to
>
> 2) do checks, then pass it down to unchecked functions:
> void func(P1 p1, P2 p2, ...)
> {
> Â if (!IsOK(p1)) return;
> Â if (!IsOK(p2)) return;
>
> Â return unchecked_func(p1, p2, ...);
> }
>
> This actually CAN (somewhat) work with code in between - after every
> single check you call another smaller function. Â But you end up with a
> cascade of functions (hard to follow) and you quickly run out of good
> names or reuse the same name if the param types have changed. Â But it
> can also be helpful if the inner functions can be reused in cases
> where you, say, already had a DC or HPEN or something. ie
>
> void func(P1 p1, P2 p2, ...)
> {
> Â Q q = getQ(p1);
> Â if (!IsOK(q)) return;
> Â return foo(q, p2,...); Â // then foo(Q,...) then assumes Q, handles
> p2, maybe calls down another layer.
> }
>
>
> 3) use gotos
> Maybe gotos are evil, but I've seen 'goto cleanup' or 'goto
> endoffunction' and it doesn't really bother me that much. Â It is sort
> of a poor man's 'finally' construct. As long as you are not going to
> multiple labels, or going back to the top (ie only 'goto' to labels
> closer to the end of the function) I can live with it.
>
>
> 4) mulitple returns strewn about
> I think there are a few reasons to avoid multiple returns, but a few
> of them need revisiting. Â In particular, one reason was that multiple
> returns tended to cause resources to go un-destructed. Â At least in
> the C days. Â But now, if we are coding to be exception safe, then
> basically we are dealing with multiple return points whether we want
> to or not. Â ie if an exception happens in the middle of the function,
> then that's where we are 'returning' from. Â Or at least realize that
> if everything is RAII and exception safe, then the code is also
> 'return safe'.
> Multiple return points might still be harder to read and reason with
> (although not much different than multiple breaks), but at least it
> should now be 'safe'.
> P.S. multiple returns were once hard to debug, (you had to put
> breakpoints at every return if you didn't want to miss your exit) but
> now you can typically put a breakpoint at the closing '}' of the
> function itself, and catch them all (although you still might not know
> which one it was).
>
> 5) exceptions
> I've tried throwing exceptions, but found a few things
> a) some of the errors were not 'exceptional'
> b) it felt odd (to me) to catch exceptions thrown within the same
> function (as opposed to catching exceptions thrown from lower levels)
> c) it didn't look like less code than other solutions
> Of course, there are cases where the errors SHOULD be thrown up to a
> higher level, and that does make the code cleaner (particularly if
> there is NO catching in the current function) so it would make sense
> to use it in those situations.
>
> 6) Your 'Breakable' idiom
> Well, I haven't tried it. Â I really dislike macros. Â Probably that
> would be enough to stop me. Â Not sure I like
>
> Â for (bool executed=false;!executed;executed=true)
>
> any better. Â I'd have to comment that, and then why not use a macro,
> which would be a comment at the same time.
>
> 7?) Â Interestingly, I think I would be fine with it, if it was built
> into the language. Â ie why not allow a break out of 'unnamed' blocks?
> (besides breaking some existing code with these blocks within loops,
> of course :-)
>
> Â Â {
> Â Â Â Â if (bad(x))
> Â Â Â Â Â Â break;
> Â Â Â Â y = ....;
> Â Â Â Â if (!y)
> Â Â Â Â Â Â break;
> Â Â }
>
> I think I recall proposals for 'named' Â breaks, and multilevel breaks as well?
>
>
> Anyhow, I think that is a long way for me to just say "I feel your
> pain", and I wish there was a nicer solution (that was part of the
> language). Â I might even try your style. Â If I DID start using it
> regularly, I'd definitely want it to be in boost, even if it was tiny
> - because then it would become a known and understood idiom. Â But I'd
> prefer better language support instead.
Actually the D language has such named blocks and jumps to parent
loops from child ones and so forth, might look at it as an example...