多相型バリアント

SML#の多相型バリアントの表現のところを見てて、よくわからないので
JavaScriptに移植して理解しようとしてみた。

http://www.pllab.riec.tohoku.ac.jp/smlsharp/ja/?Resorces%2FProgrammingExamples%2FVariants
このへんや、
http://www.pllab.riec.tohoku.ac.jp/smlsharp/ja/?VariantSource
この辺見て、JavaScriptに移植する。+JavaScriptでもdのmixinっぽくってのをやってみた。

SMLはOCamlとかよりも、結構Cに近いというか、JavaScriptに近い感じがします。
Ocamlがやっぱり、括弧やら、セミコロンやらをうまく使ってるよなぁとも思うのでした。

function variant(s) {
	var ss = s.split("|");
	for(var i = 0; i < ss.length; i++) {
		var sss = ss[i];
		var m = sss.match(/\s*([^\s\(]+)\s*\(([^\)]*)\)/);
		var m2 = m[2].split(",");
		for (var j = 0; j < m2.length; j++) m2[j] += ":" + m2[j];
		eval(m[1] + "=function("+m[2]+"){return function(M){return M."+m[1]+"({"+m2.join(",")+"});};};");
	}
}
function fn(str) { return function(_) {with(_){ return eval("_="+str); }}; }
Object.prototype.toString = function() {
	var str = "";
	for(var i in this) {
		str += i + ":"+ this[i]+",";
	}
	if (str != "") str = str.substring(0,str.length-1);
	return "{" + str + "}";
}
variant("CPoint(x,y)|PPoint(r,theta)");
var r = {
	CPoint: fn("Math.sqrt(x * x + y * y)"),
	PPoint: fn("r")
};
var theta = {
	CPoint: fn("(Math.atan(x / y)/Math.PI)*180.0"),
	PPoint: fn("theta")
};
var x = {
	CPoint: fn("x"),
	PPoint: fn("Math.cos(theta/180.0*Math.PI)*r")
};
var y = {
	CPoint: fn("y"),
	PPoint: fn("Math.sin(theta/180.0*Math.PI)*r")
};
var toCPoint = {
	CPoint: fn("_"),
	PPoint: fn("CPoint(PPoint(r,theta)(x),PPoint(r,theta)(y))(toCPoint)")
};
var toPPoint = {
	CPoint: fn("PPoint(CPoint(x,y)(r), CPoint(x,y)(theta))(toPPoint)"),
	PPoint: fn("_")
};
var p1 = CPoint(10.0, 10.0);
var p2 = PPoint(14.1421356, 45.0);
alert(p1(r));
alert(p2(r));
alert(p1(theta));
alert(p2(theta));
alert(p1(x));
alert(p2(x));
alert(p1(y));
alert(p2(y));
alert(p1(toCPoint));
alert(p2(toCPoint));
alert(p1(toPPoint));
alert(p2(toPPoint));

/*
function iterator(L,f) {
	map (function(x){return x(f);}, L);
}
var myPointList = [P1,P2];
function myPointLstIter(x) { iterator(myPointList, x); }
myPointLstIter(distance);
myPointLstIter(angle);
*/