Skip to content

Instantly share code, notes, and snippets.

@steos
Created March 29, 2011 13:28
Show Gist options
  • Save steos/892344 to your computer and use it in GitHub Desktop.
Save steos/892344 to your computer and use it in GitHub Desktop.
naive currying in javascript and php (yes! really!)
// this is a helper for the curry function which does partial
// function application; given the function fn, an optional scope
// self and a variable number of arguments this function returns
// a new function which is bound to self with all arguments applied.
// example:
// function add(a, b) {
// return a + b;
// }
// var inc = partial(add, null, 1);
// assert(inc(4) == 5);
function partial(fn, self) {
var parr = Array.prototype;
var args = parr.slice.call(arguments, 2);
return function() {
return fn.apply(self, args.concat(parr.slice.call(arguments)));
};
}
// this function applies currying to the given function, that means, that
// a new function is returned which if called with too few arguments
// returns a partially applied function.
// example:
// curry(function(z,y,x) {
// return [x,y,z];
// });
// var vec2 = vec3(0);
// var vec1 = vec2(0);
// assert(vec1(1) == [1,0,0])
// assert(vec2(1,2) == [1,2,0])
function curry(fn, self) {
return function() {
if (arguments.length < fn.arity) {
var args = [fn, self];
args = args.concat(Array.prototype.slice.call(arguments));
var p = partial.apply(null, args);
p.arity = fn.arity - arguments.length;
return curry(p, self);
}
else {
return fn.apply(self, arguments);
}
};
}
<?php
/**
* partial function application
*
* @params callable $fn the function you want to apply partially
*
* example:
* function add($a, $b) {
* return $a + $b;
* }
* $inc = partial('add', 1);
* assert($inc(1) == 2);
*/
function partial() {
$args = func_get_args();
$fn = array_shift($args);
return function() use ($fn, $args) {
$myargs = func_get_args();
return call_user_func_array($fn, array_merge($args, $myargs));
};
}
/**
* function currying
*
* @param callable $fn the function to curry
*
* example:
* $vec3 = curry(function($z, $y, $x) {
* return array($x, $y, $z);
* });
* $vec2 = $vec3(0);
* assert($vec2(1,2) == array(2,1,0));
* $vec1 = $vec2(7);
* assert($vec1(3) == array(3,7,0));
*/
function curry($fn, $arity = null) {
$ref = new ReflectionFunction($fn);
if ($arity == null) {
$arity = $ref->getNumberOfRequiredParameters();
}
return function() use ($arity, $fn) {
$numArgs = func_num_args();
if ($numArgs < $arity) {
$args = func_get_args();
array_unshift($args, $fn);
$p = call_user_func_array('partial', $args);
$newArity = $arity - $numArgs;
return curry($p, $newArity);
}
else {
return call_user_func_array($fn, func_get_args());
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment