Skip to content
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

Closed
wants to merge 9 commits into from
Closed

Conversation

lvivski
Copy link

@lvivski lvivski commented Feb 15, 2012

_.curry, _.partialRight, _.partialAny, _.partial (as _.bind alias) covered with tests.

Call curried function without arguments to explisitly call it.

@paulmillr
Copy link

_.bind will do the job.

@jashkenas I think we should add _.curry alias to _.bind, it's not the first issue with _.curry.

@lvivski
Copy link
Author

lvivski commented Feb 15, 2012

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++]
Copy link
Collaborator

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.

Copy link
Author

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

Copy link
Collaborator

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).

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! :)

@domenic
Copy link

domenic commented Feb 15, 2012

Please understand the difference between currying and partial function application, guys.

Your partial method is indeed partial application, whereas bind and your so-called "curry" are unrelated to actual currying.

@alexindigo
Copy link

How about currying without changing the context? (re: #467 )

@ghost
Copy link

ghost commented Feb 16, 2012

@alexindigo _.bind(this, ...) or _.bind(null, ...). The latter will execute the bound function in the default global scope.

@michaelficarra
Copy link
Collaborator

@alexindigo: _.curry = function(fn){ return _.partial.apply(_, [fn].concat(_.rest(arguments))); }

@alexindigo
Copy link

@kitcambridge Here is difference between _.bind(this), _.bind(null) and _.curry http://jsfiddle.net/CqG7n/

@michaelficarra I already implemented _.curry and even sent pull request, but somehow Underscore maintainers are under impression that _.curry is the same as _.bind(func, null). My pull request #467

@ghost
Copy link

ghost commented Feb 16, 2012

@alexindigo Ah, I see. Thanks for the clarification; very helpful.

@michaelficarra
Copy link
Collaborator

@alexindigo: I was saying that this pull request could be modified to assign _.curry in that way instead of using it as an alias to _.bind.

@alexindigo
Copy link

@michaelficarra I'm ok with either way as long as it has similar api and it's in the core. :)

@lvivski
Copy link
Author

lvivski commented Feb 16, 2012

My initial implementation of _.curry was really the same as _.bind and implemented partial application not currying.

So now _.partial is an alias for _.bind. _.curry implements the real currying like in haskell, and _.partialSkip is like partial application but with skipped parameters.

@alexindigo your implementation is not currying but partial application.

@masylum
Copy link

masylum commented Feb 16, 2012

+1 for curry

@alexindigo
Copy link

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" curry would be useful?

@lvivski
Copy link
Author

lvivski commented Feb 16, 2012

I don't think it's really good point to post code samples here, but I currently use curry for node.js mailing system 'cause mailer accepts lots of different params and it is completely useful in this case.

@alexindigo
Copy link

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.

lvivski added 2 commits April 2, 2012 14:22
you have to re-curry your function if you want to get closure, not to call the method
@jashkenas
Copy link
Owner

If we do merge this -- we'll probably just want the curry function alone. But I agree that use cases would be nice to see first. In an eagerly evaluated language, where is this useful that bind can't handle?

@alexindigo
Copy link

@jashkenas You can check this pull request #467 and it has real life examples as well ( http://jsfiddle.net/CqG7n/ )

@alexindigo
Copy link

@jashkenas Just noticed your comment in the other thread :)

@domenic
Copy link

domenic commented Apr 2, 2012

Just going to reiterate that, if merged, this really needs to be called partial instead of curry. Sorry, I'm being dumb.

@jashkenas
Copy link
Owner

I'm afraid that http://jsfiddle.net/CqG7n/ ain't real-world examples, and the director example doesn't use curry.

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.

@jashkenas jashkenas closed this Apr 4, 2012
@machineghost
Copy link

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):
http://mochi.github.com/mochikit/doc/html/MochiKit/Base.html#fn-partial

Now, _.bind currently does this, but requires that you also bind the "this" of the function. That has two downsides:

  1. Sometimes you'd like to keep the current "this" of a function
  2. It makes the syntax messier/harder to understand:
    fooWithBar = _.bind(foo, this, bar);
    vs.
    fooWithBar = _.partial(foo, bar);
    (Obviously it's not a huge difference, but I do think the intent of the latter code is much more obvious).

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);
or:
_.each(someFunction, someArray, newThis);

It'd also be nice if you could do:

.each(.partial(someFunction, extraVar), someArray);
or:
_.each(someFunction, someArray, undefined, extraVar);

@machineghost
Copy link

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.

@alexindigo
Copy link

I think we can publish a book out of this thread. :)

@jasonkuhrt
Copy link

I believe I have a use-case. I tried to find a nice generic way to make an extend_each function using partial application techniques but failed miserably. I looked through this thread's code samples but still couldn't succeed so I resorted to a one-off solution. Not sure if this is a "real-world" use case. All I can say is it happened in the, uh, real world.

  Template.global_data = (globals_dictionary)->
    extend_each = (things_to_extend, extensions)->
      _.each things_to_extend, (something_to_extend)->
        _.extend something_to_extend, extensions

    extend_each Template, globals_dictionary

@jashkenas
Copy link
Owner

Looks like a good use case where partial application wouldn't help you very much ;)

@jasonkuhrt
Copy link

@jashkenas That might explain the troubles I had! haha

@machineghost
Copy link

Just FYI for anyone who finds this thread and does want a partial function you can "roll your own" by adding just one line:

_.mixin({partial: function(func) {return _.bind.apply(null, [func, null].concat(_.rest(arguments)))}})

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.

@jdalton
Copy link
Contributor

jdalton commented Dec 8, 2012

@machineghost

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.
Note: There's no explicit this binding so it's that of the object it's assigned to:

// 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"

@jashkenas
Copy link
Owner

@machineghost -- How are you using partial in your code base? Mind pasting a bit or two?

@junosuarez
Copy link

@jashkenas I'm using it to turn n-ary callback-taking functions into unary callback-taking functions, eg:

function doSomethingAsync(arg1, arg2, arg3, cb) {
}

var continuation = _.partial(doSomethingAsync, "arg1", 2, 3);

Basically, I really hate syntax with null arguments, and I don't like having to have fn.bind(null, ...) calls - to me, partial is more clear. I can understand if that doesn't warrant inclusion in underscore, though.

@machineghost
Copy link

@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:

  1. I have a recursive parsing function that's been pre-bound using _.bindAll as part of being a class's method. It takes some data and a node, parses it, then runs itself again on _.each child node of the data. However, parsing the child nodes (and their child nodes and so on) requires knowledge of the original data, so I feed partial(this.recursiveDataParser, data) in to the _.each call. Without the partial I'd still have access to the data (as it's in-scope from the original call), but my arguments would be messed up (because the function takes data, node, and if I just fed it to each it would get node as its args).

  2. I have a few cases where I want a function that just returns X (usually because it's the base implementation of a method, and sub-classes are going to define more interesting versions). Partial + identity makes that super-simple: _.partial(_.identity, true) // always return true

  3. I inherited a bunch of legacy event handlers that were like $(foo).click(function() {SomeLib.handleEvent('foo')}), and was able to simplify them to $(foo).click(_.partial(SomeLib.handleEvent, 'foo'));

  4. I sometimes have functions that essentially do the same exact thing, except for one variable worth of info (eg. getFooLabel and getBarLabel where the logic is ... var type = isFoo ? 'foo' : 'bar'; //bunch of identical logic). I could just fold them in to one function (getLabel(foo)), but I want the consumers of my API to have separate functions for each (it makes sense in the context of the API, not so much when I use foo and bar). In these cases I can define getLabel(isFoo) and then define getFooLabel: _.partial(getLabel, true) and getBarLabel: _.partial(getLabel, false) and still keep my code DRY.

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 _.bind instead? Absolutely. I just like to keep my code as clean and as readable as possible, and I think _.partial(foo, bar) explains what I'm trying to do to the reader more effectively than to _.bind(foo, null, bar).

Plus, the code-golfer in me likes the few less characters ;-)

@jashkenas jashkenas reopened this Dec 10, 2012
@junosuarez
Copy link

_.partial(_.identity, x) - you've just rediscovered the K combinator 👍 Look how functional we're getting!

@mcordingley
Copy link

+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.

@mcordingley
Copy link

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

@jdiamond
Copy link

I hope that _.partial() will pass the current this through to the partially applied function.

I just ran some tests and both @jdalton's and @mcordingley's versions do, but @machineghost's version does not.

test('partial preserves this', function() {
    var person = {
        name: 'Jason',
        speak: _.partial(function() {
            return 'name is ' + this.name;
        })
    };

    equal(person.speak(), 'name is Jason');
});

@machineghost's version is binding to null (which becomes the global object in non-strict mode). I assume he's not using this in his functions so wouldn't be affected by this behavior.

@machineghost
Copy link

@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 _.bind instead of _.partial, so whenever I'm using my own partial it's because I've either got:
A) a pre-bound function, or
B) a function doesn't reference this

Those conditions aren't necessarily going to be true of anyone else using _.partial though, so I completely agree that the partial function should not mess with the context at all, and I fully support either @jdalton's or @mcordingley's implementation.

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 :-)

@mcordingley
Copy link

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.

@mcordingley
Copy link

Packaged up the two functions in separate commits in case @jashkenas wants to merge them.

19caf9f6e3efa18ff1b439175df49c032686d304 for _.partial()
6b23a9e13f91b3a3c60d07e5776d7511a6e7167f for _.partialRight()

@jashkenas jashkenas closed this in 789da94 Jan 30, 2013
@jashkenas
Copy link
Owner

@mcordingley -- thanks for your partial implementation. I've added it to Underscore, and it'll go out with the next release.

@jdalton
Copy link
Contributor

jdalton commented Jan 30, 2013

@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`

@mcordingley
Copy link

@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

@fogus
Copy link
Contributor

fogus commented Feb 20, 2013

The main problem with adding _.partial to Underscore is that the default argument ordering is not amenable to its use. That is, the pattern is often function foo(someCollection, fun) in Underscore. Where partial really shines is in creating new functions from existing functions, so to have the collection first eliminates the power-potential to say something like:

var summation = _.partial(_.reduce, function(s, n) { return s + n });

summation([1,2,3,4,5])
// TypeError: Object 1,2,3,4,5 has no method 'call'

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. _.partial(_.reduce, [undefined, function(s, n) { return s + n })])) or swap the Underscore arguments. Neither seems particularly appealing. Better would be to add proper currying so that we could do something like the following:

var summation = curry2(_.reduce)(function(s, n) { return n + s })

summation([1,2,3,4,5])
//=> 15

This is not a slam against the addition of _.partial, only another data point for the ticket.

@mcordingley
Copy link

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.

@CrossEye
Copy link

CrossEye commented Apr 9, 2013

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 flip defined, then we could simply do:

var summation = _.partial(_.flip(_.reduce), function(s, n) { return s + n });

summation([1,2,3,4,5]);
// => 15

flip should be very easy:

var _.flip = function(fn) {
    return function(a, b) {return fn.call(this, b, a);};
}

Or of course there could simply be a rightPartial version as some have suggested, which would be still more general.

I know that _.partial is there now. I suppose I should open up a ticket asking for _.flip.

@mcordingley mcordingley mentioned this pull request Apr 9, 2013
@mcordingley
Copy link

CrossEye,

I'm thinking that flip is the more general of the two, as partialRight can then be constructed as a higher-order function with the two.

That said, I have opened a pull request for flip and further discussion of it should probably take place there: #1062

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.