-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Added Curry and Partial Methods #474
Conversation
@jashkenas I think we should add |
and what about partial? |
var args = slice.call(arguments, 1); | ||
return function(){ | ||
for (var i = 0, arg = 0; i < args.length && arg < arguments.length; i++) | ||
if (args[i] === void 0) args[i] = arguments[arg++] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer if(args[i] !== _) ...
. That way _
is used as a skipped argument so that someValue
, where it just happens to be undefined
, is allowed as an argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would lead to some confusion cause "_" is underscore object itself and it will be passed as a parameter several times
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's why it's perfect. fn(_, _, 3)(1, 2)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I came to this issue tracker specifically to request a partial function; way to read my mind! :)
Please understand the difference between currying and partial function application, guys. Your partial method is indeed partial application, whereas |
How about currying without changing the context? (re: #467 ) |
@alexindigo |
@alexindigo: |
@kitcambridge Here is difference between @michaelficarra I already implemented |
@alexindigo Ah, I see. Thanks for the clarification; very helpful. |
@alexindigo: I was saying that this pull request could be modified to assign |
@michaelficarra I'm ok with either way as long as it has similar api and it's in the core. :) |
My initial implementation of So now @alexindigo your implementation is not currying but partial application. |
+1 for curry |
I don't think we should jump out of our pants trying to implement haskel in javascript. Can you provide real world example where "true" |
I don't think it's really good point to post code samples here, but I currently use |
I'm not asking to show your production code, but some dumbed version, to illustrate the point. As far as I can think mailer params available at same time, and to have core function which returns 5 levels deep function in function doesn't sound as most effective solution. |
you have to re-curry your function if you want to get closure, not to call the method
If we do merge this -- we'll probably just want the |
@jashkenas You can check this pull request #467 and it has real life examples as well ( http://jsfiddle.net/CqG7n/ ) |
@jashkenas Just noticed your comment in the other thread :) |
|
I'm afraid that http://jsfiddle.net/CqG7n/ ain't real-world examples, and the director example doesn't use Closing for the time being, but let's reopen this if someone comes up with some good real-world examples for currying in JS apps/pages/projects. |
I'm a little confused by this ticket's comment thread. It looks like Underscore is not going to get a "partial" function; am I reading things correctly? If not, please disregard this comment, but if so I'd really like to advocate for a partial function (without a "curry" function or any other Haskell stuff). First off, let me just clarify what I mean by "partial": a function which takes another function and 1+ arguments, and "hard-codes" those arguments in to the function before returning it. Here's a better description from Mochikit (a similar library to Underscore that's now defunct): Now, _.bind currently does this, but requires that you also bind the "this" of the function. That has two downsides:
As for real-world uses for "partial", just look at any underscore function that takes functions as arguments. Let's say I have a addFooToBar function, and an array of foos (foos). I can do: _.each(addFooToBar, foos); but there's no way to get bar in to there; to do so I need to do: .each(.bind(addFooToBar, this, bar), foos); which changes the "this" of addFooToBar and looks less clean compared to: .each(.partial(addFooToBar, bar), foos); And then, for bonus points, it'd be really nice if all of the collection functions supported implicit partial arguments the way they support implicit binding. What I mean by that is that you can do: .each(.bind(someFunction, newThis), someArray); It'd also be nice if you could do: .each(.partial(someFunction, extraVar), someArray); |
P.S. Ok, I know my "real-world" examples all involved foos and bars, but hopefully you can understand the utility even so; if not I'd be happy to provide examples from my actual code. |
I think we can publish a book out of this thread. :) |
I believe I have a use-case. I tried to find a nice generic way to make an
|
Looks like a good use case where partial application wouldn't help you very much ;) |
@jashkenas That might explain the troubles I had! haha |
Just FYI for anyone who finds this thread and does want a partial function you can "roll your own" by adding just one line:
It'd be great if Underscore incorporated that and further exposed the world to the joys of functional programming ... but since that looks unlikely, hopefully that one-line fix can be the next best thing. |
For those interested I've also included _.partial in Lo-Dash. // dumb example
var greet = function(greeting, name) {
return greeting + ', my name is ' + this.name;
};
var person = { 'name': 'Bob', 'speak': _.partial(greet, 'Hi') };
person.speak();
// => "Hi, my name is Bob" |
@machineghost -- How are you using |
@jashkenas I'm using it to turn n-ary callback-taking functions into unary callback-taking functions, eg:
Basically, I really hate syntax with null arguments, and I don't like having to have |
@jashkenas Pasting the actual code examples wouldn't be too helpful (for them to be meaningful I'd have to include a bunch of other un-related stuff), but I can describe some of the cases:
All of the above are real life, in production use-cases. #1 is kind of special-case, but I think #2 and #4 are fairly common, and #3 is probably somewhat common in the special case of re-factoring terrible legacy code. Could they all be handled with Plus, the code-golfer in me likes the few less characters ;-) |
|
+1 vote for this. I want to be able to pre-assign variables from the calling context to callback functions without messing with the value of 'this' that gets assigned by the code that ultimately invokes the callback. In this particular case, it's an Ajax handler with jQuery. From reading this thread, it looks like binding to NULL just sets the context to the window. Thanks for an awesome library. |
I just read through the commits for this pull. Isn't the point of a partial application without binding to be to apply the arguments with 'this' as the function's context? At the time of the function executing, 'this' will resolve to whatever it normally is. e.g. A DOM element if the partial function is supplied to a jQuery event callback. Setting it as context requires that we know the context when we call the _ function to perform a partial application. For a simplistic but working example, see: https://gist.github.com/4347830 |
I hope that I just ran some tests and both @jdalton's and @mcordingley's versions do, but @machineghost's version does not.
@machineghost's version is binding to |
@jdiamond You are correct, my implementation is a bit naive. Sort of by definition, if I want to partial anything that needs binding, I just use Those conditions aren't necessarily going to be true of anyone else using Honestly, I just provided mine in the first place because it didn't look like partial was going to be added to Underscore, and since I found the concept useful I thought I'd share my (in retrospect flawed) implementation in case someone else wanted to be able to create partial functions. Given that my implementation helped argue for adding partial to Underscore, it's already done far more than I hoped :-) |
I do like the idea of having a partialRight() function like @lvivski has in the pull request. I updated my gist to include a version that preserves the context's "this" while applying the originally provided arguments from the right. That is, the first argument after the function to which we are partially applying will be the last argument to that function and each successive argument will work in to the left. |
Packaged up the two functions in separate commits in case @jashkenas wants to merge them. 19caf9f6e3efa18ff1b439175df49c032686d304 for _.partial() |
@mcordingley -- thanks for your |
@jashkenas Something to consider is just using a modified form of your bind fallback (adding a flag). That way you can preserve behavior of calling a partial function as a constructor. var func = function() {},
partialed = _.partial(func, 'a', 'b');
new partialed instanceof func // could be `true` like it is with `_.bind` |
@jashkenas Thank you very much. I'm glad to have contributed. To anyone flipping through this thread after the fact and looking for _.partialRight(), you can get it as a mixin from here: https://gist.github.com/4680147 |
The main problem with adding
Because the collection gets in the way. Sadly there is not a lot to do about this except to create some crazy version of partial that takes an arg spec (e.g.
This is not a slam against the addition of |
From this thread and from around the Web, there seems to be some confusion regarding the difference between currying and partial application. I just found this article that nicely explains the difference between the two. After reading it, I would argue that both _.partial() and _.curry() should exist. I think _.partial() is correctly implemented according to the article's definition of it. I think I saw a correct implementation of _.curry() earlier in this thread. |
I think fogus's comment is almost correct. This would not be a great fit without one additional function included as well. If we had
Or of course there could simply be a I know that |
CrossEye, I'm thinking that That said, I have opened a pull request for |
_.curry
,_.partialRight
,_.partialAny
,_.partial
(as_.bind
alias) covered with tests.Call curried function without arguments to explisitly call it.