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>
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.