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?
_______________________________________________
phobos mailing list
[email protected]
http://lists.puremagic.com/mailman/listinfo/phobos

Reply via email to