Skip to content

Instantly share code, notes, and snippets.

@cowboy
Created January 29, 2015 16:17
Show Gist options
  • Save cowboy/d59b3adfd906d1fcd597 to your computer and use it in GitHub Desktop.
Save cowboy/d59b3adfd906d1fcd597 to your computer and use it in GitHub Desktop.
JavaScript: I've finally found a use case for currying in JavaScript!
// You can have multiple optional arguments, but only if the arguments
// can be distinguished from one another (in this example, by type)
function optionalUnambiguous(myString, myNumber) {
if (typeof myString === 'number') {
myNumber = myString;
myString = null;
}
if (myString == null) { myString = 'default'; }
if (myNumber == null) { myNumber = 0; }
return [myString, myNumber];
}
optionalUnambiguous() // ["default", 0]
optionalUnambiguous('test') // ["test", 0]
optionalUnambiguous(123) // ["default", 123]
optionalUnambiguous('test', 123) // ["test", 123]
// What happens when you can't distinguish between the optional arguments?
// You run into problems!
function optionalAmbiguous(myValue1, myValue2) {
if (arguments.length === 1) {
// which value did they pass in: myValue1 or myValue2?
}
}
// Instead of a single function with multiple optional arguments, why not
// specify a series of functions that each accept a single argument? This
// way there's no possible ambiguity.
//
// I guess I've finally found a use case for currying in JavaScript!
// http://benalman.com/news/2012/09/partial-application-in-javascript/
function optionalWhatever(myValue1) {
if (myValue1 == null) { myValue1 = 'default1'; }
return function(myValue2) {
if (myValue2 == null) { myValue2 = 'default2'; }
return [myValue1, myValue2];
}
}
optionalWhatever()() // ["default1", "default2"]
optionalWhatever('test')() // ["test", "default2"]
optionalWhatever()(123) // ["default1", 123]
optionalWhatever('test')(123) // ["test", 123]
@CosmoScriv
Copy link

Poured over the example trying to see if I would like the technique. But I'm not completely sold on this technique for implementing optional parameters. Typically I would use optional parameters when I want to enhance an already existing function or have flexibility down the road to add more parameters. But if had an existing function and I wanted to add another optional parameter all the existing calls would have to change to call the function twice.

1st draft:

exampleFx : function(foo) {
Return [foo];
}

exampleFx(‘1stDraft’);

// next I decide I want to extend this function to accept an additional optional parameter:

exampleFx : function(foo) {
return function(bar) {
return [foo, bar];
}
}

exampleFx(‘1stDraft’); // this version of the function no longer returns the array and instead returns a function. To get the array I have to call the returned function.

@Markus-ipse
Copy link

Since the order of the arguments still matter in this example

optionalWhatever()()          // ["default1", "default2"]
optionalWhatever('test')()    // ["test", "default2"]
optionalWhatever()(123)       // ["default1", 123]
optionalWhatever('test')(123) // ["test", 123]

I don't quite see how it's that much better than optionalWhatever(null, "test"), etc.
or am I missing something?

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