Skip to content

Instantly share code, notes, and snippets.

@kagamilove0707
Created June 15, 2013 04:37
Show Gist options
  • Save kagamilove0707/5786920 to your computer and use it in GitHub Desktop.
Save kagamilove0707/5786920 to your computer and use it in GitHub Desktop.
HaskellのArrowをJavaScriptで再現してみました>ω<
(function() {
'use strict';
function toArray(n, args) {
return Array.prototype.slice.call(args, n);
}
function extend(obj, it) {
return Object.keys(obj).reduce(function(it, name) {
it[name] = obj[name];
return it;
}, it);
}
function Arrow(f) {
return extend(Arrow.operators, f);
}
Arrow.operators = { };
Arrow.operators['then'] = Arrow.operators['>>>'] = function(g) {
var f = this
;
return Arrow(function(h) {
f.apply(this, [function() {
g.apply(this, [h].concat(toArray(0, arguments)));
}].concat(toArray(1, arguments)));
});
};
function parallel(h, procs) {
var results = []
, count = 0
, next = function(i) {
return function(x) {
results[i] = x;
count++;
if(count === procs.length) {
h(flatten(results));
}
}
}
;
procs.forEach(function(proc, i) {
setTimeout(function() {
proc(next(i));
}, 0);
});
}
function flatten(xs) {
return Array.isArray(xs) ? xs.reduce(function(xs, x) {
return xs.concat(flatten(x));
}, []) : xs;
}
Arrow.operators['&&&'] = function(g) {
var f = this
;
return Arrow(function(h) {
var args = toArray(1, arguments)
;
parallel(h, [
function(h) { f.apply(this, [h].concat(args));},
function(h) { g.apply(this, [h].concat(args));}]);
});
};
Arrow.operators['***'] = function(g) {
var f = this
;
return Arrow(function(h, args) {
parallel(h, [
function(h) { f.apply(this, [h, args.slice(0, args.length - 1)]);},
function(h) { g.apply(this, [h, args[args.length - 1]]);}]);
});
};
Arrow.operators['nth'] = function(n, g) {
var f = this
;
return Arrow(function(h) {
var args = toArray(1, arguments)
;
f.apply(this, [function(args) {
g(function(x) {
h(args.slice(0, n).concat([x], args.slice(n + 1)));
}, args[n]);
}].concat(args));
});
};
Arrow.operators['first'] = function(g) {
return this['nth'](0, g);
};
Arrow.operators['second'] = function(g) {
return this['nth'](1, g);
};
Arrow.operators['|||'] = function(g) {
var f = this
;
return Arrow(function(h, x, y) {
x != null ? f(h, x) : g(h, y);
});
};
Arrow.operators['+++'] = function(g) {
var f = this
;
return Arrow(function(h, x, y) {
return x != null ? f(function(x) {
h(x, null);
}, x) : g(function(y) {
h(null, y);
}, y);
});
};
Arrow.operators['left'] = function(g) {
var f = this
;
return Arrow(function(h, xy) {
f(function(x, y) {
x != null ? g(function(x) {
h([x, null]);
}, x) : h([null, y]);
}, xy);
});
};
Arrow.operators['right'] = function(g) {
var f = this
;
return Arrow(function(h, xy) {
f(function(x, y) {
y != null ? g(function(y) {
h(null, y);
}, y) : h(x, null);
}, xy);
});
};
Arrow.operators['<+>'] = function(g) {
var f = this
;
return Arrow(function(h) {
var args = toArray(1, arguments)
;
f.apply(this, [function(x, y) {
x != null ? h(null, y) : g(function(x, y) {
h(x , y);
}, x);
}].concat(args));
});
};
Arrow.operators['>=>'] = function(g) {
var f = this
;
return Arrow(function(h) {
var args = toArray(1, arguments)
;
f.apply(this, [function(x, y) {
x == null ? g(function(x, y) {
h(x, y);
}, y) : h(x, null);
}].concat(args));
});
};
Arrow['app'] = Arrow(function(h, fx) {
fx[0](fx[0], h);
});
Arrow['loop'] = Arrow(function loop(x, f) {
f(function(x) {
loop(x, f);
}, x);
});
Arrow['value'] = function(x) {
return Arrow(function(h, _) {
h(x);
});
};
Arrow['id'] = Arrow(function(h, x) {
h(x);
});
Arrow['proc'] = function(f) {
return Arrow(function(h, _) {
f(h);
});
};
Arrow.operators['applyArrow'] = function(x) {
return this(function() { }, x);
};
Arrow.operators['callArrow'] = function(f) {
return this(f, undefined);
};
Arrow.operators['async'] = function(g) {
var f = this
;
g = g || function() { };
setTimeout(function() {
f.callArrow(g);
});
};
module.exports = Arrow;
})();
var arrow = require('./control-arrow')
, fs = require('fs');
arrow.proc(function(next) {
fs.readFile('control-arrow.js', 'UTF-8', next);
})['>=>'](function(next, txt) {
arrow.proc(function(next) {
fs.writeFile('dist.txt', txt, next);
})['>=>'](function(next) {
next(null, txt);
}).async(next);
})['>>>'](
arrow(function(next, err) {
console.log('error', err);
})['|||'](function(next){
console.log('ok');
})
).async();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment