Comparators
See original GitHub issueThis will be my third stab at implementing this functionality. The basic premise is that my equality comparison methods like startsWith
, includes
and equal
aught to support specifying how to compare the values. Currently they use ===
, and they really aught to use Object.is
. In the main that is straightforward. It’s really equal
that’s the nasty bit.
The problem is this: equal aught to be able to compare things that aren’t iterables. This library already has some functionality that isn’t exactly related to iterables, e.g. the new isObject
method. It seems silly to defined equal
in such a way that equal(3, 3)
should return false or throw an error. There is a correct result, and that is true
. But now we have a problem. If equal can compare anything, there will be no foolproof way of knowing whether an argument passed to equal is intended to be a comparator or a value to be compared. What are our options to go about fixing this? As I see them the two basic ways to go are:
- Keep the comparator as the (potential) first argument but do something clever to distinguish it.
- Make a factory that takes a comparator and returns an equal method that does nothing magical with its arguments at all.
Each has advantages and disadvantages. The disadvantage of the factory is relatively obvious I think. It won’t look or work quite like our other methods. Either it will be forced currying equal(comparator)(...values)
which looks weird when you want the default comparator equal()(...values)
, or we’ll have to pick a factory name for the factory, e.g. equalFactory
. None of it rolls off the tongue.
The disadvantage of currying is that it risks being confusingly magical. We could assume that any call to equal
which is given only a single argument is configuring the comparator, e.g. equal(comparator)
. I think this risks weirdness since our equal method is variadic. It may be used with a spread, and then dynamic changes in the length of the array could cause the shape of the output to change from a boolean to a function. Better I think would be to require the comparator to be tagged, e.g. a function with a Symbol.for('@iter-tools/comparator')
property. The consumer wouldn’t have to know about the symbol, they would just write equal(comparator((a, b) => a - b === 0), ...values)
. I think this is the best solution. I’m going to go ahead and try implementing it.
Issue Analytics
- State:
- Created 3 years ago
- Comments:7 (7 by maintainers)
Top GitHub Comments
Oh I should have used the new discussions feature for this. Next time. Good discussing this with you, self!
I guess for
includesSeq
there’s no need to go to that trouble as the current curry definition can handle a comparator. That just leavesincludes
. I don’t think that’s ambiguous now that I think about it. If you get one function before your iterable it’svalue
. If you get two functions before your iterable they’recomparator
,value
.Wow I’m done!