Created
January 29, 2015 16:17
-
-
Save cowboy/d59b3adfd906d1fcd597 to your computer and use it in GitHub Desktop.
JavaScript: I've finally found a use case for currying in JavaScript!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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] |
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
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.