Use flag enum instead of bool.

To prevent Boolean Blindness.
This commit is contained in:
H. S. Teoh 2014-11-04 15:56:00 -08:00
parent 74d5923430
commit ab72e3cf51

View file

@ -4548,8 +4548,18 @@ Group!(pred, Range) group(alias pred = "a == b", Range)(Range r)
} }
// Used by groupBy.
/**
* Specifies whether a predicate is an equivalence relation.
*/
enum IsEquivRelation : bool
{
no, /// Predicate is not an equivalence relation
yes, /// Predicate is an equivalence relation
}
// Used by implementation of groupBy. // Used by implementation of groupBy.
private struct GroupByChunkImpl(alias pred, bool isEquivRelation, Range) private struct GroupByChunkImpl(alias pred, IsEquivRelation isEquivRelation, Range)
{ {
alias fun = binaryFun!pred; alias fun = binaryFun!pred;
@ -4626,7 +4636,7 @@ private struct GroupByChunkImpl(alias pred, bool isEquivRelation, Range)
} }
// Implementation of groupBy. // Implementation of groupBy.
private struct GroupByImpl(alias pred, bool isEquivRelation, Range) private struct GroupByImpl(alias pred, IsEquivRelation isEquivRelation, Range)
{ {
alias fun = binaryFun!pred; alias fun = binaryFun!pred;
@ -4714,21 +4724,21 @@ private struct GroupByImpl(alias pred, bool isEquivRelation, Range)
* are considered equivalent if $(D pred(a,b)) is true. In unary form, two * are considered equivalent if $(D pred(a,b)) is true. In unary form, two
* elements are considered equivalent if $(D pred(a) == pred(b)) is true. * elements are considered equivalent if $(D pred(a) == pred(b)) is true.
* *
* The optional parameter $(D isEquivRelation), which defaults to false for * The optional parameter $(D isEquivRelation), which defaults to
* binary predicates if not specified, specifies whether $(D pred) is an * $(D IsEquivRelation.no) for binary predicates if not specified, specifies
* equivalence relation, that is, whether it is reflexive ($(D pred(x,x)) is * whether $(D pred) is an equivalence relation, that is, whether it is
* always true), symmetric ($(D pred(x,y) == pred(y,x))), and transitive ($(D * reflexive ($(D pred(x,x)) is always true), symmetric ($(D pred(x,y) ==
* pred(x,y) && pred(y,z)) implies $(D pred(x,z))). When this is the case, $(D * pred(y,x))), and transitive ($(D pred(x,y) && pred(y,z)) implies
* groupBy) can take advantage of these three properties for a slight * $(D pred(x,z))). When this is the case, $(D groupBy) can take advantage of
* performance improvement. * these three properties for a slight performance improvement.
* *
* Note that it is not an error to specify $(D isEquivRelation) as false even * Note that it is not an error to specify $(D IsEquivRelation.no) even when
* when $(D pred) is an equivalence relation; the resulting range will just be * $(D pred) is an equivalence relation; the resulting range will just be
* slightly slower than it could be. However, if $(D isEquivRelation) is * slightly slower than it could be. However, if $(D IsEquivRelation.yes) is
* specified as true yet $(D pred) is actually $(I not) an equivalence * specified yet $(D pred) is actually $(I not) an equivalence relation, the
* relation, the behaviour of the resulting range is undefined. * behaviour of the resulting range is undefined.
* *
* Unary predicates always imply $(D isEquivRelation) is true, since they are * Unary predicates always imply $(D isEquivRelation.yes), since they are
* internally converted to the binary equivalence relation $(D pred(a) == * internally converted to the binary equivalence relation $(D pred(a) ==
* pred(b)). * pred(b)).
* *
@ -4753,11 +4763,11 @@ private struct GroupByImpl(alias pred, bool isEquivRelation, Range)
auto groupBy(alias pred, Range)(Range r) auto groupBy(alias pred, Range)(Range r)
if (isInputRange!Range) if (isInputRange!Range)
{ {
return groupBy!(pred, false, Range)(r); return groupBy!(pred, IsEquivRelation.no, Range)(r);
} }
/// ditto /// ditto
auto groupBy(alias pred, bool isEquivRelation, Range)(Range r) auto groupBy(alias pred, IsEquivRelation isEquivRelation, Range)(Range r)
if (isInputRange!Range) if (isInputRange!Range)
{ {
static if (is(typeof(binaryFun!pred(ElementType!Range.init, static if (is(typeof(binaryFun!pred(ElementType!Range.init,
@ -4766,7 +4776,7 @@ auto groupBy(alias pred, bool isEquivRelation, Range)(Range r)
else static if (is(typeof( else static if (is(typeof(
unaryFun!pred(ElementType!Range.init) == unaryFun!pred(ElementType!Range.init) ==
unaryFun!pred(ElementType!Range.init)))) unaryFun!pred(ElementType!Range.init))))
return GroupByImpl!((a,b) => pred(a) == pred(b), true, Range)(r); return GroupByImpl!((a,b) => pred(a) == pred(b), IsEquivRelation.yes, Range)(r);
else else
static assert(0, "groupBy expects either a binary predicate or "~ static assert(0, "groupBy expects either a binary predicate or "~
"a unary predicate on range elements of type: "~ "a unary predicate on range elements of type: "~
@ -4784,13 +4794,13 @@ auto groupBy(alias pred, bool isEquivRelation, Range)(Range r)
[2, 3] [2, 3]
]; ];
auto r1 = data.groupBy!((a,b) => a[0] == b[0], true); auto r1 = data.groupBy!((a,b) => a[0] == b[0], IsEquivRelation.yes);
assert(r1.equal!equal([ assert(r1.equal!equal([
[[1, 1], [1, 2]], [[1, 1], [1, 2]],
[[2, 2], [2, 3]] [[2, 2], [2, 3]]
])); ]));
auto r2 = data.groupBy!((a,b) => a[1] == b[1], true); auto r2 = data.groupBy!((a,b) => a[1] == b[1], IsEquivRelation.yes);
assert(r2.equal!equal([ assert(r2.equal!equal([
[[1, 1]], [[1, 1]],
[[1, 2], [2, 2]], [[1, 2], [2, 2]],