Comments (29)
+1
from ramda.
Fixed in c1c986b
from ramda.
I think this should this be done with uniqWith
, differenceWith
, et. al. as well
from ramda.
i'm changing my mind on this. what if the objects in the list you are evaluating have complicated relations? e.g. uniqWith(function(a, b) { return a.x === b.y && a.y === b.y; }, list)
does not get captured using this approach. Then the simple prop
implementation of the *With
functions is a special case of passing a more abstract comparator.
from ramda.
EDIT: this was in response to @megawac's comment, not @buzzdecafe's.
I'm not so sure about that. I can easily see:
MyType.areEqual(a, b) {
if (!(a instanceof MyType && b instanceof MyType)) {return false;}
if (a.hash() !== b.hash()) {return false;}
if (a.testDifficultProperty1() !== b.testDifficultProperty1()) {return false;}
if (a.testDifficultProperty2() !== b.testDifficultProperty2()) {return false;}
// ...
return true;
}
uniqWith(MyType.areEqual, listOfMyType)
This can't necessarily be captured by a single key.
from ramda.
Some other libraries allow you to return an array from these functions which will compare in order.
from ramda.
@buzzdecafe: I agree regarding uniqWith, et al. But I can't see any use cases for minWith
/ maxWith
, although maybe we should rename to minBy
/ maxBy
?
from ramda.
i was also thinking *By
for single-property comparison
from ramda.
@buzzdecafe I'm also not sure that your example makes real sense, as I think all of these comparisons really need to be symmetric in the two parameters. But the general point stands.
But yes, use *By
for single-property comparisons, whether a natural property of the object or a synthesized one, *With
for a more general function. That would be a cleaner API.
from ramda.
I think the objection stands for minWith
on the same grounds. You can have a list of objects that have some crazy rules for determining which one is the smallest that is not captured in an attribute. Imagine there is some kind of pecking order ...
from ramda.
@megawac Don't understand about the array. I'm mostly ok with compose
ing reverse
if necessary. How does returning an array help?
from ramda.
Would give you the same functionality from a *By
function as a *With
ramda.maxBy(function(x) {
return [x.x, x.y]
}, [{x: 1, y: 2}, {x: 1, y: 1}, {x: 1, y: 5}, {x: 1, y: 2}]); //=> {x: 1, y: 5}
from ramda.
@CrossEye. that is essentially the way i implemented the path*
functions. In that case, should the sig of *By
be Str -> [Obj] -> Obj
? and the inital Str gets converted to prop(Str)
?
@megawac ok, that's interesting, but does not address the more complex example @CrossEye suggested
from ramda.
@megawac Got it; thought you were talking ascending vs descending. I'd rather not go there. If we get as complicated as that, I'd rather just let 'em use an arbitrary function.
from ramda.
Alright, it might be worth creating a *By
generator and a *With
generator and allowing users to decide regardless (because personally I hate having to work with a
and b
all the time [begins to look confusing])
from ramda.
@buzzdecafe I like a more general *By
for these. The key could still be entirely synthetic:
var makeSortName = fork(join(' '), prop('lastName'), always(','), prop('firstName'));
maxBy(makeSortName, people);
(untested, and don't know if we actually have join
, but should be clear.)
from ramda.
@megawac I agree, and it should be easy to implement the *By
in terms of the *With
.
from ramda.
@CrossEye that example seems like a maxWith
to me. What is the distinction of By
and With
in your mind?
btw, gotta come up with a new name for fork
from ramda.
@buzzdecafe *By
focuses on a single list item, generates a key for it. *With
is the one that knows how to do the comparison between two different items. That was the issue that started me down this trail. There was no good reason to be writing a full-fledged comparator when I often wanted to either fetch or synthesize something from a single object.
from ramda.
at present pathBy
takes a string as its first param. I'd like all of the *By
fns to have the same semantics, and passing a function is overkill to pathBy
. And I also don't wanna type-check the first arg
from ramda.
Yeah, that's a different beast, isn't it? I've been thinking about max
/min
/sort
/uniq
/difference
, which I think could all share these semantics. But path
is definitely different.
from ramda.
I disagree @buzzdecafe, I think a lookupIterator
function would be sweet for choosing how to use the given argument
from ramda.
@megawac Yes, the trouble is that it would be nice if we could have a universal semantic for the *By
and *With
, which just got different meanings on the new path
.
from ramda.
It wouldn't be hard to mix that in with an iterator
from ramda.
since pathBy
seems to be the problem child here, maybe the simplest solution is to come up with a new name for it.
from ramda.
let's rename pathBy
to pathOn
and use With
and By
semantics elsewhere as described above.
from ramda.
@megawac: We've been trying to avoid any unnecessary type-checking, making our functions as strongly-typed as feasible in JS. We definitely aren't interested in the Underscore/LoDash style of "if parameter 3 is a function do x, if it's an object, do y, and if it's a string do z." This is not to say that we have no type-checking, but there's relatively little, and that's mostly to support dynamic dispatch for extensions, such as the lazy lists, and (soon, I hope) the algebraic types.
@buzzdecafe That might be best. But can't think of a good name.
from ramda.
@buzzdecafe That sounds good.
from ramda.
The original goal of this issue was long ago satisfied. If we want to follow up on the remaining discussion, we can reopen later.
from ramda.
Related Issues (20)
- [Bug] groupBy result keys order when 0 as first character HOT 6
- R.pipe(R.tryCatch, ...) anomaly HOT 12
- clone does not clone error instance HOT 2
- swap does not work as intended
- Ramda is 3x slower because it uses the arguments object? HOT 10
- Broken link in the "Install specific functions" section of README
- how to implement insertWhile HOT 2
- R.aperture returns arbitrary/random ordering of "consecutive" elements HOT 1
- 0.29.1 Upgrade Guide HOT 11
- compose does not work with zipwith HOT 2
- R.without broke backwards compatibility on #2603 HOT 1
- update vulnerable dependencies
- update sanctuary
- bug: code coverage failing
- enhancement: update prop to include deeply nested objects
- enhancement: update path to use prop
- Support promises for pipe and pipeWith HOT 2
- illegal invocation HOT 4
- `groupBy` throws inscrutable errors when inferred to be a transducer HOT 4
- Incorrectly implementation of the 'unless' function HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ramda.