raineorshine
1/25/2015 - 6:20 AM

curry and partially apply functions or macros with sweet.js

curry and partially apply functions or macros with sweet.js

/*output*//*
var foo = 'd', bar = 'e';
console.log('a', 'b', 'c', foo, bar);
console.log('a', 'b', 'c', foo, 2, 3, 4, 5);
console.log('a', 'c', 'b');
console.log('a', 'd', 'b', 'f', 'e', 'g', foo);
function veryLongFunction() {
    console.log.apply(console, arguments);
}
veryLongFunction('a', 'b', 'c', 'd', 'e', 'f');
veryLongFunction('a', 'b', 'c', foo, bar, 'baz');
*/

macro curried {
    rule { $($id = $mac($opt (,) ...)) (,) ... ; } => {
        $(let $id = macro {
            rule { ($rest (,) $[...]) } => {
                $mac($opt (,) ..., $rest (,) $[...])
            }
            rule { } => { $id }
        }) ...
    }
}

macro partial {
    rule { $($id = $mac($opts (,) ...)) (,) ... ; } => {
        $(let $id = macro {
            case {_ ($rest (,) $[...]) } => {
                var args = [], opts = #{ $opts ... }, rest = #{ $rest $[...] },
                    i = -1, n = opts.length,
                    j = -1, k = -1;
                while(++i < n) {
                    var opt = opts[i],
                        tok = opt.token,
                        val = tok && tok.value;
                    args[++j] = val === "_" &&
                                tok.type === parser.Token.Identifier ?
                        rest[++k] : opt;
                }
                n = rest.length;
                while(++k < n) { args[++j] = rest[k]; }
                letstx $args $[...] = args;
                return #{ $mac($args (,) $[...]) }
            }
        }) ...
    }
}

macro veryLongArgsList {
    rule { ($args (,) ...) ; } => {
        console.log($args (,) ...) ;
    }
}

var foo = "d", bar = "e";

curried curriedMacro = veryLongArgsList("a", "b", "c"),
        curriedAgain = curriedMacro(foo);

curriedMacro(foo, bar);
curriedAgain(2, 3, 4, 5);


partial partialMacro = veryLongArgsList("a", _, "b"),
        partialAgain = partialMacro("d", _, "e");

partialMacro("c");
partialAgain("f", "g", foo);

function veryLongFunction() {
    console.log.apply(console, arguments);
}

curried curriedFunc = veryLongFunction("a", "b", "c"),
        curriedFuncAgain = curriedFunc(foo);

curriedFunc("d", "e", "f");
curriedFuncAgain(bar, "baz");