OCaml - function, match with et autres

Le problème exposé dans ce sujet a été résolu.

Bonjour,

En Ocaml on a les deux syntaxes suivantes :

1
2
3
4
(*cette fonction ne sert à rien*)
let rec a = function 
     |[] -> []
     |t::q -> t::(a q);;

ou bien :

1
2
3
let rec a l = match l with 
     |[] -> []
     |t::q -> t::(a q);;

Dans un cas on est pas obligé de préciser le deuxième paramètre alors que dans l’autre cas on doit le préciser. Donc je me demandais si à part cela (donc dans ce cas function permet juste un gain de temps), il y avait une réelle différence entre match with et function. Déjà je remarque, qu’avec function, on ne peut pas faire explicitement appel à l’argument. Dans le sens ou par exemple on pourrait faire avec match with :

1
2
let a  l = match l with 
     |_ -> l (*or ici on ne peut pas faire directement appel à l avec function*)

Ou alors il existe un moyen mais je ne le connais pas ? Aussi au niveau de la façon dans le compilateur gère function et match with, y at-il une différence ?

De même sur plein de sites il est marqué que la curryfication est très pratique, mais je ne vois pas vraiment pourquoi (à part que c’est un gain de temps *) ? Par exemple on peut faire :

1
2
let g x y = x+y;;
let h = g 1;;(*curryfication*)

Donc on a juste pas à récrire la fonction h c’est tout, et je ne vois pas d’autres utilités de ce principe.

Enfin dernière question, quand on fait un match est-il possible de return le wildcard _ ?

Merci d’avance !

Salut,

Mes souvenirs d’OCaml sont assez épars, mais je ne crois pas qu’il y ait de réelle différence entre la version utilisant function et celle avec un match. Il me semble que les deux exploitent des sucres syntaxiques différents pour exprimer la forme complète de la définition de ta fonction qui serait la suivante.

1
2
3
let rec a = function l -> match l with
    | [] -> []
    | t::q -> t::(a q);;

Pour la curryfication, ça sert effectivement « juste » à cela, mais c’est tout de même bien pratique.

Enfin, _ n’est qu’un nom particulier pour dire de ne pas binder sur une variable le résultat du match. Mais si tu donnais un autre nom à ton pattern, tu pourrais parfaitement l’utiliser par la suite.

1
2
let a = function
    | l -> l;;

Un exemple pratique d’application partielle. Supposons que tu aies un type 'k 'v map, qui est une collection de type clef/valeur, c’est à dire qu’à un élément du type k tu peux associer une valeur du type v.

Les deux fonctions assez évidentes pour ce genre de collections sont :

1
2
3
get : 'k 'v map -> 'k -> 'v option

put : 'k -> 'v -> 'k 'v map -> 'k 'v map

Autrement dit, la capacité de lire (get) ou écrire (put) dans ta map.

Modifier une valeur existante s’écrit assez facilement avec get et put, mais le souci, c’est que ça veut dire qu’il faut parcourir la map deux fois. Ce qui se fait souvent, c’est de fournir une fonction modify qui ressemble à ça :

1
modify : 'k -> ('v -> 'v) -> 'k 'v map -> 'k 'v map

Autrement dit, tu vas appliquer la fonction donnée en paramètre à modify à la valeur, si elle existe.

Il te suffit ensuite d’écrire toutes les fonctions qui modifient tes v sous la forme ? -> v -> v pour qu’ils puissent être très facilement utilisées avec modify.

Si v est int, cela veut dire que l’on peut utiliser ta fonction g avec modify.

Avec x a pour type k, on peut imaginer écrire : modify x (g 1) m, qui aura pour conséquence d’incrémenter la valeur associée à la clef x dans la map m.

+1 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte