New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ramda 0.27.1 allPass working wrong #3114
Comments
As the doc says: The function returned is a curried function whose arity matches that of the isQueenOfSpades' length is 1, it only accept 1 argument, but you put in 3, neverthless it only process the first argument. |
If you want to check all the items that satisfy a given predicate, you can use const isQueen = R.propEq('rank', 'Q');
const isSpade = R.propEq('suit', '♠︎');
const isQueenOfSpades = R.allPass([isQueen, isSpade]);
const allAreQueenOfSpade = R.all(isQueenOfSpades)
allAreQueenOfSpade([{rank: 'Q', suit: '♠︎'}, {rank: 'Q', suit: '♣︎'}, {rank: 'Q', suit: '♠︎'}]) //=> false |
I think you're combining the idea of
Thus if we have const fn = allPass ([
(x, y) => x + y > 10,
(x, y) => x * y < 100,
(x, y) => (x - y) % 2 == 1,
]) we get the following behavior: fn (4, 5) // false -- sum < 10
fn (14, 6) // false -- even difference
fn (14, 15) // false -- product > 100
fn (14, 5) // true -- matches all predicates Note that the arity of 1This is not precisely true: because of short-circuiting, some may not actually be called. But the idea is the same. |
When I'm not familiar with ramda, I often use // Wrong way
R.allPass([isQueen, isSpade], {rank: 'Q', suit: '♠︎'})
// The correct way
R.allPass([isQueen, isSpade])({rank: 'Q', suit: '♠︎'}) which will return another function instead of the checked result. |
There are 2 categories of curried function in ramda:
I think this may also will confuse other ramda beginners? We can give people some Notes in the document, or do some type checking in the code? |
@adispring: This is an unusual case, and there are a few more like it. It mostly has to do with when we generate polyadic functions. It's hard to curry this our normal way when it could be used as allPass([x => x > 10, x => x < 100], 42) //=> true
allPass([x => x > 10, x => x < 100], 7) //=> false but also as allPass([(x, y) => x + y > 10, (x, y) => x * y < 100], 14, 5) //=> true
allPass([(x, y) => x + y > 10, (x, y) => x * y < 100], 14, 15) //=> false or as allPass([(x, y, z) => x + y >= z, (x, y, z) => x + z >= y, (x, y, z) => y + z >= x], 5, 12, 13) //=> true
allPass([(x, y, z) => x + y >= z, (x, y, z) => x + z >= y, (x, y, z) => y + z >= x], 5, 12, 18) //=> false So we do this in two stages. I don't see any good alternative to that. It would probably be a good idea to capture this more explicitly in the documentation comments, though. While the type signature is reasonable, |
If we begin to handle this issue -- Better error messaging and type-checking : #2998, we can check the type and the number of arguments people passed in, then give them some tips on development stage. |
That's I wanted to do, thanks! And thank you for your detailed respones! |
Yes, do you want to make a pr to add "see also", note or more descriptions to make that more clearly. |
This would still be significantly more work than other functions. I'm pretty sure that we would never be able to use our standard currying mechanism for functions like this. Our usual curry interrogates the function we pass in to determine how many arguments to expect. But here it's not just that It's not that I don't think we could write such a thing, but then trying to keep it synchronized with our regularly curried functions when we add features (as, for instance, the way discussed in #2998) to the currying code could turn pretty ugly. I suppose we could use this function as a test case and see how we might share code with the standard curry. |
So I tried to test that modified example on screenshot, and that goes wrong: it must be false
The text was updated successfully, but these errors were encountered: