Version française
Home     About     Download     Resources     Contact us    
Browse thread
Re: [Caml-list] Pattern matching
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Luc Maranget <luc.maranget@i...>
Subject: Re: [Caml-list] Pattern matching
> 

> Fabrice Le Fessant a écrit :
> 
> >  (* couples 4 = (1,2) (1,3) (1,4) (2,3) (2,4) (3,4) *)
> >  let couples = function n ->
> >    let rec couplesCPS = function
> >      | (n,_) -> [ ]
> >      | (i,n) -> (i,n) :: couplesCPS (i+1, i+2)
> >      | (i,j) -> (i,j) :: couplesCPS (i, j+1)
> >    in    couplesCPS (1,2)
> >  ;;
> [...]
> 
> let succ n = n + 1;;
> 
> Le langage introduit nombre de quantificateurs existentiels ou
> universels, ne serait-ce que dans la définition même des fonctions :
> je lis la définition de la fonction successeur : « soit successeur la
> fonction qui a tout n de N associe (n + 1) ». Cela n'a jamais posé la
> moindre difficulté aux programmeurs qui, dans la fonction couple - à
> votre image - comprennent tous que n est déjà liée tandis que i et j
> ne le sont pas.
> 
> D'accord, j'utilise quand je peux la syntaxe :
> let succ = function n -> n + 1;;
> (mais le compilateur en n'admettant pas let f = function x y -> vous
> force parfois à utiliser cette horreur de syntaxe)
Je ne comprends pas trop tous ces arguments.
Il n'en reste pas moins que
  1. Les fonctions sont des citoyens de première classe en Caml
    et qu'il n'est pas toujours nécessessaire de leur donner un nom.
    Dans ce cadre la notation (fun x -> ...) est logique.

    Mais, comme vous semblez le dire vous même, ``let f = fun x -> ...''.
    c'est lourd.
      Il y a donc une notation ``let f x = ... ''


Je coupe un example de syntaxe bizarre, sur la base de ce qu'on peut
écrire de mauvais programmes dans tous les langages.
Je trouve plus intéressant de chercher à définir un style de bonne
programmation.



> let delta = function
>   | 0 -> 1
>   | _ -> 0
> ;;
> D'accord car on a disjoint l'ensemble de définition
> 
> let delta = function
>   | i when (i = 0) -> 1
>   | i -> 0
> ;;
> à mettre en parallèle avec :
> let delta = function
>   | i when (i = 0) -> 1
>   | j -> 0
> ;;
> Etrange car on a attrappé deux fois de suite une variable qui prend
> des valeurs sur tout l'ensemble de définition et on ne comprend pas
> très bien pourquoi cette variable est muette.
Je pense qu'elle est muette parce que c'est comme ça. Et je l'admet en
toute modestie (j'exagère bien entendu).
> Si l'on accepte cela
> (qui est conséquence de l'absence de liaison explicite de i une seule
> fois pour toutes), pourquoi n'accepterait-on pas qu'une variable dans
> le motif soit déjà liée : ce serait tout aussi pratique.
> 
Ben moi ça ne me choque pas.
if blabla then let i = ... else let i = ... 
ne me pose que peu de problème, parceque les deux i ne coexistent pas.

let i = .. in
if blabla then
  let i = ...
else
  ...
me fait dresser le sourcil, sans me choquer outre mesure.
Tout ça dépend probablement de l'intention du programmeur.





Au fond Je ne comprends pas l'argument et je dis que, sur cet exemple
l'emploi du filtrage est mal venu.
Si j'étais prof (et je le suis) il faut écrire

let delta i = if i=0 then 1 else 0
Qui me semble la bonne facon de procéder.
(ou alors match i with 0 -> 1 | _ -> 0, tout aussi bien)

Je decouvre souvent des matchs sans justification dans des copies
d'élèves et je me demande à chaque fois pourquoi ne pas utiliser des
constructions simples (ici le if ou le match sans when) partout où
elles s'appliquent.

Maitenant personne ne veut supprimer le when, nous sommes sans doute
d'accord. Mais on les verra ailleurs.



> Ou alors adopter pour unique syntaxe quelque chose comme
> let couple = function n ->
>    let rec coupleCPS = function (i,j) ->
>      match (i,j) with
>        | (n,_) -> [ ]
>        | (_,n) -> (i, j) :: coupleCPS (i+1, i+2)
>        | (_,_) -> (i, j) :: coupleCPS (i, j+1)
>      in
>    coupleCPS (1,2)
> ;;
Sans rire c'est exactement ce que je recommanderais, non pas au
concepteurs du compilo, mais aux programmeurs, surtout débutants
(et d'ailleurs j'ecris généralement dans ce style).
Ne pas utliser le filtrage dans les définitions de fonction, toujours
utiliser des match explicites.

A part ça, le fait de rigidifier la syntaxe ne change rien à l'affaire
de mon point de vue. Les variables des filtres sont liantes comme les
autres, c'est une
règle simple et compréhensible, que je refuse de laisser tomber pour
une amelioration d'expressivité (une égalité cachée) dont je persite à
croire qu'elle a fort peu d'intérêt.


> 
> On peut utiliser i, j et n dans les motifs et dans le reste du code
> car les trois variables ont été liés correctement au préalable
Correctement hum ? Les variables sont liés par les motifs, c'est
simple et direct.

De toute façon, ça ne correspond pas au langage actuel Aet de loin,
car dans Caml actuel, toutes les constructions liantes (ou presque)
sont exprimées par des motifs, dont les variables sont tout simplement
liantes.

l'écriture  ``fun (x,y) -> ... ''' revèle que la règle est
 expression = ... | fun pat -> expression | ...

(pat pouvant être une variable d'ailleurs) les variables de pat sont
liantes comme partout. Le tout est de le savoir.

Je crois comprendre l'idée de privilègier en quelque sorte les
variables liées dans un ``fun''.
Mais bon, pourquoi alors les deuxièmes liaisons de x dans
(fun x -> (fun x -> ...) )
et dans
(fun x -> match y with x -> 
auraient-elles une signification différente ?

Sincèrement, ça ne tient pas la route. Ça va trop contre un principe
général et bien établi à l'heure actuelle.
C'est dur à expliquer et sans grande portée pratique.



Ce qui pourrait être admis (pour progresser à petits pas sur
l'existant) serait, dans certains circonstances
l'interdiction (ou le déconseil par un avertissement) de
l'introduction de variables homonymes.
Genre
(fun x -> match y with x -> ...)
                       ^^
                        |
Warning: pas bo, dangereux.

Mais bof c'est certainement moins simple à bien spécifier que ça en a
l'air.



> 
> < alors le simple fait de definir 'i' avant la fonction
> < change le sens de la fonction par rapport a quand
> < 'i' n'etait pas defini ?
> 
> Voyez un peu le code de Madore ! L'égalité change de sens dans chacune
> des propositions
>     let f x = x+1;;
>     lot f x = x+1;;
Madore a fait une erreur, la syntaxe ne l'aide pas, mais bon.
Elle est du même ordre que = / == en C.


En conclusion j'insisterait sur la nécessité pour chacun de se définir
un style propre (dans les deux sens) d'écriture qui limite ce type de
danger. Bizarrement (cf. l'exemple du if) cela revient souvent à
choisir la  construction de programmation adaptée à ce que l'on
shouhaite exprimer et, parfois,  à s'abstenir de traits avancés.
(Soit si ya pas de motif pourquoi utiliser un match).
Rapelons au passage que filtrer c'est d'abord destructurer.


D'autre part, lorsque l'on a effectivement besoin de ces traits
avancés, il vaut mieux, je crois, se contraindre à les exprimer
toujours de la même façon simple.

Ensuite et j'enfonce le clou. Chaque fois que j'utilise des variables
de même nom (y compris dans des liasons qui ne semble pas poser de pb,
comme les let) j'arrête la programmation en mode automatique et je me
pose la question de pourquoi je fais ça, c'est à chaque fois une
situation qui demande de toute façon d'y regarder à deux fois, (en
particulier parceque la résistances aux modifications ultérieures
chute) et la réponse est rarement qu'il y a égalité implicite entre
variables homonymes.


--Luc

-------------------
Bug reports: http://caml.inria.fr/bin/caml-bugs  FAQ: http://caml.inria.fr/FAQ/
To unsubscribe, mail caml-list-request@inria.fr  Archives: http://caml.inria.fr