try/catch idiom in std.datetime
Jonathan M Davis
jmdavisProg at gmx.com
Mon Nov 18 00:42:21 PST 2013
On Monday, November 18, 2013 00:14:24 Andrei Alexandrescu wrote:
> On 11/17/13 11:28 PM, Jonathan M Davis wrote:
> > On Sunday, November 17, 2013 22:32:46 Andrei Alexandrescu wrote:
> "Too much of a good thing" comes to mind (as does with the massive and
> repetitive unittests in std.datetime). If code looks and feels meh, it
> probably is. Just apply good judgment instead of rote adherence to rules.
Well, my coding style has adjusted over time, and I'm tending to put fewer
blank lines in cases like this, precisely because it's not terribly pretty.
> as does with the massive and repetitive unittests in std.datetime
Those are quite valuable IMHO, as being thorough has caught a lot of problems,
and as we've discussed (and disagreed on) before, I prefer unit tests to be
dead simple in order to reduce the odds of them being buggy, even if that
means that they're more verbose. I have done some work however to move the
tests toward using loops instead in order to reduce the number of lines of
code, but I have quite a bit still to do there. I'll probably get back to that
after I finish with splitting std.datetime, but I haven't finished that yet
because of how busy I've been the past few months. So, everything takes
forever... Oh well, I should get back to that soon enough.
> >> 0. Do nothing. This is as good as it gets.
> >
> > Well, it works just fine as-is, but it would be kind of nice to be able to
> > solve the problem in a less verbose manner (though you're talking about
> > saving only a few lines of code).
>
> I'm also concerned about generated code size and overall efficiency. It
> looks like the assert(0) insertions are there simply to validate the
> design (they only fail if Phobos has an internal error), so there should
> be some means to remove them in release builds. We don't have such a
> possibility at the moment.
Well, the assertions are there to validate the design, but the try-catches are
required to make the function nothrow, and I'd feel very funny having an empty
catch block, though having it compiled out in -release wouldn't necessarily be
a bad idea (which could probably be done if a function which returned false
where used in the assertion instead of a constant).
> >> 2. Relax the nothrow guarantees. After all, nothrow is opt-in.
> >
> > I'm not quite sure what you're suggesting here.
>
> What I meant is, not everything that is nothrow needs to be annotated as
> such.
So, you're suggesting that nothrow be inferred?
> > @property FracSec fracSec() const nothrow
> > {
> >
> > trusted-nothrow
> > {
> >
> > auto hnsecs = removeUnitsFromHNSecs!"days"(adjTime);
> >
> > if(hnsecs < 0)
> >
> > hnsecs += convert!("hours", "hnsecs")(24);
> >
> > hnsecs = removeUnitsFromHNSecs!"seconds"(hnsecs);
> >
> > return FracSec.from!"hnsecs"(cast(int)hnsecs);
> >
> > }
> >
> > }
>
> That can be done at library level.
Well, it is being done at the library level right now via try-catch.
> >> 4. ...?
> >
> > We now have std.exception.assumeWontThrow, which works reasonably well
> > when
> > you need to wrap a single call as opposed to several, but it has the same
> > problem as enforce in that it uses lazy, which is definite performance
> > hit. So, in most cases, I'd be more inclined to just use a try-catch, and
> > if it's more than one expression, you pretty much need to use try-catch
> > or scope(failure) instead anyway, since you wouldn't want to wrap whole
> > function bodies in a call to assumeWontThrow (assuming that you even
> > could).
>
> Again, one problem here (in addition to the blowup in code size and
> decay of readability) is we're talking about an internal design
> validation, not meaningful runtime semantics. There should be a way to
> remove the baggage.
I think that that would require a language change of some kind, because it
would require that the compiler recognize that the check can go away in
-release, which would effectively mean having the try-catch block be optimized
away somehow when compiling with -release. Using scope(failure) for that
wouldn't change anything, as it would just mean that the compiler was
inserting the try-catch statements for you. It would just be slightly less
verbose.
Maybe the compiler can be changed to optimize out try-catch blocks if the
catch block just contains an assertion? That would at least get rid of the
overhead of the idiom, even if it didn't make it less verbose. If we can't get
the compiler to recognize the idiom and optimize out the unnecessary code,
then if we want it to be optimized out, I think that we'll be forced to add
something to the language which the compiler _does_ recognize and therefore
can compile out when appropriate - unless someone can come up with some great
idea for improving nothrow, but that seems a lot like it would be moving
towards not needing @trusted anymore, because the compiler would figure that
out for you. I don't see how you could get away from having to have the
programmer tell the compiler that they're sure that the function which can
throw won't throw inside the nothrow function, because that requires human
judgement just like @trusted does, though it should generally be easier for a
programmer to be sure that something won't throw than it is to be sure that
it's actually @safe.
- Jonathan M Davis
More information about the Digitalmars-d
mailing list