List.ml d'ocaml en javascript

Contenu du snippet

J'ai recode une partie de List.ml d'ocaml, de la facon dont ces fonctions sont codees en ocaml, histoire de montrer qu'on pouvait coder fonctionnel en javascript.

les alert que j'ai mis en commentaires servent a tester ces fonctions. idem pour les deux lignes suivantes
var a = List.coller (0) (List.coller (4) (List.coller (2) (List.coller (5) (List.coller (6) (List.coller (1) (List.coller (-7) (List.coller (9) (List.Vide))))))));
var b=List.coller (1) (List.coller (3)(List.Vide));

c'est evidement une tres mauvaise idee d'utiliser ca dans un programme ensuite, car ca "risque" d'etre un peu lent... Ouais, recoder une liste chaineee en javascript, c'est pas une bonne idee...

Ce qu'il manque a javascript :
separer la notion de valeur de la notion de variable (pouvoir faire un let fonctionnel et pas une affectation imperative)
les types algebriques

Source / Exemple :


<html>
<head>
	<title>javascript : du fonctionnel ocaml like</title>
</head>
<body>

<script type="text/javascript">

//curry
function add (x){ return function(y){return x+y;}}
//document.write(add(4)(5));
function compose (func){
	return function (g){ return function (x){ return f(g(x));; } }
}
//function f(x){return x*x;}
//function g(x){return x+1;}
//document.write(compose(f)(g)(1));

function raise(a, li){
	alert("raise : "+a+li);
}

var List={};
List.Vide = {vide:1}
List.hd=function (li){
	if (List.Vide==li){
		raise('List.hd', li);
	}else{
		return li.hd;
	}
};
List.tl=function (li){
	if (List.Vide==li){
		raise('List.tl', li);
	}else{
		return li.tl;
	}
};
List.coller=function (e){
	return function (li){
		var a={};
		a.hd=e;
		a.tl=li;
		return a;
	}
}
List.toString=function(li){
	if (List.Vide==li){
		return "";
	}else {
		var hd = List.hd(li);
		var tl = List.tl(li);
		if (tl==List.Vide){
			return hd;
		}else{
			return hd+", "+List.toString(tl);
		}
	}
}
//controle des effets de bords
//var a=List.Vide;
//var b=List.coller (0) (List.coller (1) (List.coller (2) (a)));
//alert(List.hd(  List.tl(b)));
//alert(List.hd(a)) // doit renvoyer wtf

var a = List.coller (0) (List.coller (4) (List.coller (2) (List.coller (5) (List.coller (6) (List.coller (1) (List.coller (-7) (List.coller (9) (List.Vide))))))));

var b=List.coller (1) (List.coller (3)(List.Vide));

List.len=function (li){
	if (li==List.Vide){
		return 0;
	}else{
		return 1+ List.len (  List.tl(li)  );
	}
}

List.rev = function (li){
	var f = function (acc, li){
		if (li==List.Vide)
			return acc;
		else
			return f (
				List.coller(List.hd(li))(acc),
				List.tl(li)
			);
	}
	return f (List.Vide, li);
}

//alert(List.toString(a));
//alert(List.toString(List.rev(a)));
//alert(List.len (a) );

List.map = function (fonction) {
	return function (li){
		if (li==List.Vide)
			return List.Vide;
		else
			return List.coller
				(fonction(List.hd(li)))
				(List.map (fonction)(List.tl(li)));
	}
}
/*
En ocaml, on a le tail rec qui nous permet d'ecrire rev_map de facon plus optimisee que map, en js, c'est pas forcement le cas

(par optimisee, j'entends : suppression de la recursivite lors de l'execution)

  • /
List.rev_map = function (fonction) { return function (li){ var f = function (acc, li){ if (li==List.Vide) return acc; else return f (List.coller(fonction(List.hd(li)))(acc),List.tl(li)); } return f (List.Vide, li); } } List.filter = function (fonction) { return function (li){ if (li==List.Vide) return List.Vide; else{ var hd=List.hd(li); if (fonction(hd)) return List.coller (hd) (List.filter (fonction) (List.tl(li))); else return List.filter (fonction) (List.tl(li)); } } } //alert(List.toString(List.filter (function(x){return x%2==0;}) (a) )); List.rev_append = function (liste1) { return function (liste2){ if (liste1==List.Vide){ return liste2; }else{ var hd=List.hd(liste1); var tl=List.tl(liste1); return List.rev_append (tl) (List.coller (hd) (liste2) ); } } } List.append = function (liste1) { return function (liste2){ if (liste1==List.Vide){ return liste2; }else{ return List.coller (List.hd(liste1)) (List.append (List.tl(liste1)) (liste2) ); } } } //alert( List.toString (List.rev_append(a)(b)) ); </script> </body> </html>

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.