CrowdHailer / fn.js

A JavaScript library built to encourage a functional programming style & strategy. - http://eliperelman.com/fn.js
MIT License
399 stars 30 forks source link

Prevent fn.curry from currying a function more than once #14

Closed jpotterm closed 10 years ago

jpotterm commented 10 years ago

This makes fn.curry check to see its argument has already been curried. If it has, there is no need to curry it again. This improves performance, because if you curry a function more than once, it has to call through a stack of functions to get to the real one. In my testing, after currying a function 5,000 times the original way it took 24ms to execute the function. After currying it 5,000 times in the new way it only took 1ms to execute. Also, running a function that was curried 10,000 in the old way caused a crash, whereas in the new way 10,000 curries is the same as 1 curry.

You can imagine the situation where a function takes an operator, for example eq, and wants to curry it.

function find(eq, collection) {
    eq = fn.curry(eq);
    ...
}

It's nice not to have to worry about whether or not eq was already curried before it was passed to find.

var eq = fn.curry(fn.op['===']);
find(eq(1), collection);
eliperelman commented 10 years ago

While I do like to see an increase in performance, I'm not in favor of injecting state into passed arguments. Quoting from the fn.js homepage:

fn.js internals force avoidance of side effects, object mutation, and function state.

If possible, I would like to see this achieved by not injecting state into userland arguments.

jpotterm commented 10 years ago

It's not injecting state into the passed arguments. It only sets the curried attribute on the function that it returns. It does not violate referential transparency. Given the same arguments it will return the same thing every time.

eliperelman commented 10 years ago

Ah, you are correct, I had misread your change as injecting into handler.