Git Product home page Git Product logo

curry's Introduction

CURRY

A curry function without anything too clever (... because hunger is the finest spice)

browser support

Why

If you don't know currying, or aren't sold on it's awesomeness, perhaps a friendly blog post will help.

API

curry

var curry = require('curry');

//-- creating a curried function is pretty
//-- straight forward:
var add = curry(function(a, b){ return a + b });

//-- it can be called like normal:
add(1, 2) //= 3

//-- or, if you miss off any arguments,
//-- a new funtion that expects all (or some) of
//-- the remaining arguments will be created:
var add1 = add(1);
add1(2) //= 3;

//-- curry knows how many arguments a function should take
//-- by the number of parameters in the parameter list

//-- in this case, a function and two arrays is expected
//-- (fn, a, b).  zipWith will combine two arrays using a function:
var zipWith = curry(function(fn, a, b){
    return a.map(function(val, i){ return fn(val, b[i]) });
});

//-- if there are still more arguments required, a curried function
//-- will always return a new curried function:
var zipAdd = zipWith(add);
var zipAddWith123 = zipAdd([1, 2, 3]);

//-- both functions are usable as you'd expect at any time:
zipAdd([1, 2, 3], [1, 2, 3]); //= [2, 4, 6]
zipAddWith123([5, 6, 7]); //= [6, 8, 10]

//-- the number of arguments a function is expected to provide
//-- can be discovered by the .length property
zipWith.length; //= 3
zipAdd.length; //= 2
zipAddWith123.length; //= 1

curry.to

Sometimes it's necessary (especially when wrapping variadic functions) to explicitly provide an arity for your curried function:

var sum = function(){
	var nums = [].slice.call(arguments);
	return nums.reduce(function(a, b){ return a + b });
}

var sum3 = curry.to(3, sum);
var sum4 = curry.to(4, sum);

sum3(1, 2)(3) //= 6
sum4(1)(2)(3, 4) //= 10

curry.adapt

It's a (sad?) fact that JavaScript functions are often written to take the 'context' object as the first argument.

With curried functions, of course, we want it to be the last object. curry.adapt shifts the context to the last argument, to give us a hand with this:

var delve = require('delve');
var delveC = curry.adapt(delve);

var getDataFromResponse = delveC('response.body.data');
getDataFromResponse({ response: { body: { data: { x: 2 }} } }); //= { x: 2 }

curry.adaptTo

Like curry.adapt, but the arity explicitly provided:

var _ = require('lodash');
var map = curry.adaptTo(2, _.map);
var mapInc = map(function(a){ return a + 1 })

mapInc([1, 2, 3]) //= [2, 3, 4]

installation

node/npm

npm install curry

amd

define(['libs/curry.min'], function(curry){
    //-- assuming libs/curry.min.js is the downloaded minified version from this repo,
    //-- curry will be available here
});

browser

If you're not using tools like browserify or require.js, you can load curry globally:

<script src="libs/curry.min.js"></script>
<script>
    <!-- curry available here -->
</script>

โˆโˆ

curry's People

Contributors

aperiodic avatar dominictarr avatar hughfdjackson avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

curry's Issues

Add a license

It's important to have a license so large organizations know if they are legally able to use the code. The lack of a license file is blocking me from using this library at work.

Provide an alternative curry that accepts an arity

As a user, I want to be able to set cap the arity of a function to a different level than the .length suggests. This may be because i'm currying library code I didn't create, legacy code I did, or code generated through higher-order functions that don't preserve the correct .length property.

Acceptance:

  • A new function should be provided, with the signature fn, int -> fn, currying a function to the arity provided as the second arg.

Bug in `curry.adaptTo`

Instead of unshifting the last argument it's shifting the first argument, note that the example in the readme is ok because for 2 arguments the statements above are equivalent however the following fails

var dataFromResponse = curry.adapt(function dataFromResponse(o, a, b, c) {
  return o[a][b][c]
})
var context = { response: { body: { data: { x: 2 }} } }
// should be {x: 2} but instead it's invoked as
// dataFromResponse('body', 'data', context, 'response')
dataFromResponse('response')('body')('data')(context)

curry.adapt

As a developer, I would love to be able to not have to write code such as:

var delve = curry(function(property, object){ return require('delve')(object, property); });

An adapt function would help, that would shift the 'context' argument (usually the first) to be the last argument.

var delve = curry.adapt(require('delve'));

Additionally, an adaptTo function may be needed, allowing arity to be set:

var myFoo = function(a, b, c, d){ ... })
var curriedFoo = curry.adaptTo(3, function(a, b, c, d){ ... })

Would be equal to:

var curriedFoo = curry(function(b, c, a){ return myFoo(a, b, c) })

Alternative implementation

The code written here for the switch case is too verbose. I wonder why has the following approach not been taken?

function curry (func) {
  return function curried () {
    const args = [].slice.call(arguments)
    if (func.length === args.length) {
      return func.apply(this, args)
    } else {
      args.unshift(this)
      return curried.bind.apply(curried, args)
    }
  }
}

Support correct arity reporting

As a user, I would expect:

A) The .length attribute to correctly report the number of remaining arguments required:

var add = curry(function(a, b){ return a + b })
add.length //= 2
add(1).length //= 1

B) A curried version of a curried function to work correctly:

var add = curry(curry(function(a, b){ return a + b }))
add(1)(2) //= 3

Use Cases:
A) defensive currying
B) creating higher order functions that can work on any arity of input function.
C) not gettin' confused at the REPL

Acceptance criteria:

  • Arity of curried functions is reported accuralty.

curry a function where arguments have been swapped

I need to put an argument last so I put together a simple swap function. Could you please help me understand why this don't work?

curry = require('curry');

function swap(fn, i1, i2) {
  return function() {
    var args = Array.prototype.slice.call(arguments);
    var t = args[i1];
    args[i1] = args[i2];
    args[i2] = t;
    console.log(args); // for testing purposes
    return fn.apply(null, args);
  }
}

function sub(a,b) {return a-b}
console.log(sub(3,2));
console.log( swap(sub, 0, 1)(3,2) );
console.log( curry(sub)(3)(2) );

// Error
console.log( curry(swap(sub, 0, 1)) (3)(2) );

Any help is greatly appreciated!

Can't curry more than 10 arguments

Hi,
I'm trying to curry a function of 11 arguments, but it doesn't work. It always returns a function instead of the computed result.

Thanks,

Dario
EDIT: I'm using node.js 8.11.4

Broken link.

Hey,

Just for you to know that the blog post link seems broken.

Regards.

compose

Any chance of adding a super-useful compose to this, since currying and composition are related, and it's handier than having to include a second module all the time?

Disclaimer: I got this from the internet - I've been using this in the browser and I don't have much experience with node to know whether adding it to the prototype is a good idea or not.

Function.prototype.compose  = function(argFunction) {
    var invokingFunction = this;
    return function() {
        return  invokingFunction.call(this,argFunction.apply(this,arguments));
    }
}

Not work with ES6 default parameters

Hi there,

The following script works:

var add = curry((x, y) => {
  return x + y;
});

add(1, 2); // return 3

The following script does not work correctly:

curry((x = 0, y = 0) => {
  return x + y;
});

add(1, 2); // return 0

It may relate to the context, with apply or call somewhere.

Regards,
Dong

Readme confusion

More than an FYI than an issue; after reading the README (well, skimming at least), I don't have a clear the library is for: what do these calls result in?

This certainly doesn't resemble the API i was expecting, e.g.:

var add = curry(function(a, b){ return a + b })

add(1)(2) // 3

// plus possibly:
add(1, 2) // 3

Perhaps some clearer practical examples would help?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.