[phobos] enforce() vs. assert() for range primitives
David Simcha
dsimcha at gmail.com
Wed Aug 18 15:49:52 PDT 2010
While I was debugging std.range and std.algorithm I noticed that there's
tons of inconsistency about when enforce() vs. assert() is used for
checking input to range primitives. I think this needs to be made
consistent, and there are good arguments for both.
enforce() is arguably the way to go because we're dealing with an
external API, not internal consistency checks. According to the
guidelines in TDPL input external to an API should be checked even in
release mode.
On the other hand, assert() is arguably the way to go because ranges are
supposed to be a very efficient abstraction. Having enforce() in range
primitives that look like they should be very fast, inlined functions is
just bad practice. For example, some benchmarks I did awhile back
showed that the use of enforce() and its effect on inlining can make
using ranges slower than using opApply. Furthermore, if you're stacking
several higher-order ranges, i.e. filter!"a > 0"(map!"a *
a"(retro(someArray))) the checks may be redundant. Lastly, since arrays
are the canonical range, omitting release mode checks in library-defined
ranges would make them consistent with arrays.
Generally when I was debugging I tried to be locally consistent, i.e.
use whatever was used elsewhere in the same range. This meant being
globally inconsistent. Now that I've thought about it, my vote is for
using assert() consistently for range primitives. If ranges are filled
with tons of safety checks that have significant performance costs and
can't be disabled even in release mode, they will have failed in their
goal of providing a lightweight, efficient abstraction. enforce() can
be used for things that are intended to be called much less frequently,
like constructors. Comments?
More information about the phobos
mailing list