var partial = exports.partial = function partial(fn) {
    var args = arguments,
        func = fn; 
    [].shift.apply(args);
    return function() {
        var _args = [].slice.call(args, 0);
        [].push.apply(_args, arguments);
        return func.apply(func, _args);
    };  
};

var curry = exports.curry = function curry(fn, x) {
    var m = /\(([^\)]+)\)/.exec(fn.toString()),
        n = m[1].split(',').length,
        func = fn; 
    if (func.num_args != undefined)
        n = func.num_args;
    else
        func.num_args = n;

    if (1 == n) {
        if (x != undefined)
            return func(x);
        return func;
    } else if (n > 1) {
        if (x == undefined) {
            var _func = function(y) {
                return curry(func, y); 
            };  
            _func.num_args = n - 1;
            return _func;
        } else {
            var _func = function(y) {
                var _p = partial(func, x); 
                _p.num_args = n - 1;
                return curry(_p,  y); 
            };  
            _func.num_args = n - 1;
            return _func;
        }
    } else {
        throw "Must be called on a function that takes arguments.";
    }
};