Curry Implementations And Performance
By using a simple approach to curry and enforcing a strict signature and return value, we can make performance improvements to the traditional curry implementation.
Performance Improvement 1:
By using the full
arguments list, Crockford allows for partial application of arguments
in the returned function. While convenient, most uses of the curry method will probably only
pass a single argument. If we swap “
slice.apply...” for “
[arguments]”, curry only
uses the first argument passed and we have no need of transforming arguments into an Array
using the borrowed slice method.
We still can not use concat directly (the reason Crockford sliced his arguments in the first place)
because lacks generic qualities, see Dr. Rauschmayer’s article,
Array.prototype.concat is not generic.
Although Rauschmayer fails to point out that by applying
concat, you can achieve the desired
effect–essentially unwrapping the arguments array into separate arguments to be concatenated.
This leaves us with a
for loop as an alternative to populating the
Also consider, Crockford prevents the original function from having a context with a
passed first to
apply(). If we only plan to curry a single parameter, we can pass a context for use during invocation.
Developers who shun augmenting the native prototypes will find Alman’s function especially attractive. Another convenience of this implementation, apart from allowing partial application, invokes the original function upon satisfying all arguments. For instance, compare the invocation syntax:
While less verbose, one may find the dynamic nature of the return value troublesome to deal with.
Consider a function you would like to curry which returns a function. How do you type check the
results of calling curry? Additionally, while the optional “
n” parameter may solve
issues with functions which take
n arguments, this complicates the maintenance of such
code when curried functions change their signatures. By all definitions I can find, currying a
function should return a function (as should partial application). Alman’s example mimics the syntax
of languages like Haskell or ML where functions return a curried version if passed less than the
required number of arguments. Maybe a proper name for this function is
Performance Improvement 2:
Simply removing additional logic to always return a function result enhances curry performance. In fact, I often make “do less” the first performance enhancement of any exercise, but Crockford published first.
[Optional] Performance Improvement 3:
In cases where you will only pass simple, string/number-style arguments and you will keep the curried functions around for a while, you may want to use a memoizer to cache the functions generated. Due to the nature of test harnesses, I’ll keep this version generic.
Style Improvement 1:
With clear parameters and consistent return type, we can properly comment our new curry method and invite developers to use it:
see jsPerf tests