* [Caml-list] Pattern matching @ 2001-11-08 2:33 Diego Olivier Fernandez Pons 2001-11-09 0:26 ` Pixel [not found] ` <15339.34220.198731.791811@lachesis.inria.fr> 0 siblings, 2 replies; 16+ messages in thread From: Diego Olivier Fernandez Pons @ 2001-11-08 2:33 UTC (permalink / raw) To: Caml An english translation follows Pourrait quelqu'un expliquer les raisons pour lesquelles dans un pattern matching toutes les variables introduites sont considérées comme de nouvelles variables ? Est-ce pour des questions de choix entre égalité physique et égalité structurelle ? En effet, le code suivant : (* 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) ;; me semble nettement plus lisible que le code qu'il faut écrire en Caml actuellement : (* couples 4 = (1,2) (1,3) (1,4) (2,3) (2,4) (3,4) *) let couples = function n -> let rec couplesCPS = function | (i,_) when (i = n) -> [ ] | (i,j) when (j = n) -> (i,j) :: couplesCPS (i+1, i+2) | (i,j) -> (i,j) :: couplesCPS (i, j+1) in couplesCPS (1,2) ;; Bien sûr, si l'on passait des listes on aurait le choix entre les deux types d'égalité, mais on pourrait toujours définir une syntaxe alternative pour le cas de l'égalité physique par exemple (laisser le when pour ce cas là et autres types de comparaisons...) Pourquoi demande-t-on à un motif d'être « linéaire » ? (c'est à dire si je comprends bien la documentation qu'une variable ne peut apparaître qu'une fois dans un motif). Il est bien évident que certains motifs ne doivent pas être permis let egalite = function | (x,x) -> true | (x,y) -> false ;; # This variable is bound several times in this matching mais x est ici une nouvelle variable ce qui n'était pas le cas de n dans la fonction couple. Diego Olivier < Your function will always return 1, because variables on the < left-hand side of a pattern-match are bound like in a let < expression. Could someone explain why are variables on the left-side of a pattern-match bound like in a let expression ? Is it a problem of structural versus physical equality ? In which case, why not choosing structural by default and leaving physical for the « when » syntax ? « Patterns are linear: a variable cannot appear several times in a given pattern. In particular, there is no way to test for equality between two parts of a data structure using only a pattern (but when guards can be used for this purpose). » (manual 6.6) Could someone explain why must patterns be linear ? ------------------- 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 ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Caml-list] Pattern matching 2001-11-08 2:33 [Caml-list] Pattern matching Diego Olivier Fernandez Pons @ 2001-11-09 0:26 ` Pixel 2001-11-09 10:59 ` Luc Maranget [not found] ` <15339.34220.198731.791811@lachesis.inria.fr> 1 sibling, 1 reply; 16+ messages in thread From: Pixel @ 2001-11-09 0:26 UTC (permalink / raw) To: Diego Olivier Fernandez Pons; +Cc: Caml "Diego Olivier Fernandez Pons" <FernandezPons@iFrance.com> writes: [...] > let couples = function n -> > let rec couplesCPS = function > | (n,_) -> [ ] vs > let couples = function n -> > let rec couplesCPS = function > | (i,_) when (i = n) -> [ ] the problem is an expressivity one. Something like (function A(e) -> e | _ -> ...) become dependent on the context: is there a variable "e" in the surrounding context. This is not good. One could add some sugar allowing: > let couples = function n -> > let rec couplesCPS = function > | (@@n,_) -> [ ] where @@n force the scope of n to be non-local. But too much sugar makes the language harder to learn :) [...] > let egalite = function > | (x,x) -> true > | (x,y) -> false > ;; > # This variable is bound several times in this matching i wonder why this one is not allowed since it can't have any other meaning than the one it has in prolog. What's the reason for not having it rewritten to: > let egalite = function > | (x,x') when x=x' -> true > | (x,y) -> false maybe you're right than the kind of equality (= vs ==) may be the problem... ------------------- 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 ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Caml-list] Pattern matching 2001-11-09 0:26 ` Pixel @ 2001-11-09 10:59 ` Luc Maranget 0 siblings, 0 replies; 16+ messages in thread From: Luc Maranget @ 2001-11-09 10:59 UTC (permalink / raw) To: Pixel; +Cc: Diego Olivier Fernandez Pons, Caml About pattern matching. > > "Diego Olivier Fernandez Pons" <FernandezPons@iFrance.com> writes: is right to stress on the fact that variables in patterns are binding variables, some variable is bound to something. when you write let x = ex in let x = ex' in You certainly do not mean that ex and ex' are equal (whatever it means). On linearity : > > > let egalite = function > > | (x,x) -> true > > | (x,y) -> false > > ;; > > # This variable is bound several times in this matching > > i wonder why this one is not allowed since it can't have any other meaning > than the one it has in prolog. What's the reason for not having it rewritten > to: > Does not mean : > > let egalite = function > > | (x,x') when x=x' -> true > > | (x,y) -> false > Well, it could be that way. But it is not. This can be argueed as follows. As already said the meaning of (x,x) is not clear, should we use ``='' (and then pattern matching may last for ever, or may raise an exception (for functions)) or ``=='' (and this is not very useful). Futhermore the theory of non-left-linear rewriting is more complicated than the one of left-linear rewriting and this theory somehow applies to ML pattern matching. So my opinion is that non-linear pattern brings little benefits to users, complicates much the life of the compiler writer and may even introduce subtle bugs in users programs. --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 ^ permalink raw reply [flat|nested] 16+ messages in thread
[parent not found: <15339.34220.198731.791811@lachesis.inria.fr>]
* Re: [Caml-list] Pattern matching [not found] ` <15339.34220.198731.791811@lachesis.inria.fr> @ 2001-11-10 2:16 ` Diego Olivier Fernandez Pons 2001-11-12 10:29 ` Luc Maranget 0 siblings, 1 reply; 16+ messages in thread From: Diego Olivier Fernandez Pons @ 2001-11-10 2:16 UTC (permalink / raw) To: Caml An english abstract follows 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) J'emprunte l'exemple (terrifiant !) suivant à David Alexander Madore, lequel d'ailleurs dans son message original servait à illustrer autre chose mais peu importe let x = 42;; let lot f x = print_string "Madame Irma va maintenant répondre à la grande question :\n"; print_string "Le CAML a-t-il une syntaxe aberrante ?"; print_string "(Has CAML a weird syntax ?)"; x+1;; let f x = x+1;; lot f x = x+1;; # val x : int = 42 # val lot : 'a -> int -> int = <fun> # val f : int -> int = <fun> # Madame Irma va maintenant répondre à la grande question : # Le CAML a-t-il une syntaxe aberrante ? # (Has CAML a weird syntax ?) - : bool = true Revenons au sujet : le problème est que la définition du pattern-matching est déjà en soi étrange 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. 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. 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) ;; 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 < 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;; Diego Olivier Fabrice said « (It is my translation) How could the compiler know than "i" is a free variable while "n" is not ? And even if he could notice the difference, defining "i" would then change the meaning of the function » The problem is that in the pattern matching, variables i and j seem to be bounded several times (see the delta example).The "let" declaration is omitted (which is very usefull anyway). A strange program by David Madore is provided as well as an alternate syntax for the pattern matching. ------------------- 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 ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Caml-list] Pattern matching 2001-11-10 2:16 ` Diego Olivier Fernandez Pons @ 2001-11-12 10:29 ` Luc Maranget 2001-11-12 9:00 ` Diego Olivier Fernandez Pons 0 siblings, 1 reply; 16+ messages in thread From: Luc Maranget @ 2001-11-12 10:29 UTC (permalink / raw) To: Diego Olivier Fernandez Pons; +Cc: Caml > > 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 ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Caml-list] Pattern matching 2001-11-12 10:29 ` Luc Maranget @ 2001-11-12 9:00 ` Diego Olivier Fernandez Pons 2001-11-13 8:00 ` Fabrice Le Fessant 2001-11-13 16:09 ` [Caml-list] Pattern matching Luc Maranget 0 siblings, 2 replies; 16+ messages in thread From: Diego Olivier Fernandez Pons @ 2001-11-12 9:00 UTC (permalink / raw) To: Luc Maranget; +Cc: Caml An english abstract follows < 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. Mon « argumentation » consiste à exhiber de mauvais programmes car je considère qu'un « bon » langage ne doit pas laisser un mauvais programmeur faire du mauvais code (dans la mesure du possible). Quand je dois passer trois heures à relire le code d'une tierce personne et que je me rends compte que l'erreur est dûe à la fonction suivante : let f = function n -> let g = function | (n, i ) -> ... ^^ car le programmeur a cru que n était déjà liée (l'exemple est un peu exagéré mais bon...), j'ai tendance à taper (sans doute à tort) non sur le programmeur mais sur le concepteur du langage. < 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). Mais ??? ce code ne marche pas ! (n n'est pas lié) Je vais vous dire des choses que vous n'ignorez pas au sujet du pattern-matching, mais au moins serons nous clairs. Il y a deux usages du pattern-matching : le filtrage structurel (qui exige unification avec le motif et liaison des variables) let somme = function | [] -> 0 | [x] -> x | [x ; y] -> x + y | _ -> 0 ;; le filtrage de valeurs qui correspond à un « if then else » en plus compact (et sans introduction de nouvelles variables) let delta = function | (0, 0, 1) -> 1 | _ -> 0 ;; Ce dont je me « plains » est que la syntaxe actuelle de OCaml ne différencie pas clairement les deux et permet des mélanges qui peuvent donner lieu à du code douteux, à des erreurs difficiles à détecter... let somme = function n -> let rec sommeCPS = function | (total, k) when (k = 0) -> total | (k, total) -> sommeCPS (total + k, k - 1) ^ ^^^ in sommeCPS (0, n) ;; Ici on est en train de filtrer des valeurs, donc d'après moi il ne devrait y avoir qu'une seule liaison des variables total et k (et j'estime que la syntaxe doit forcer à ce que ce soit le cas). Il suffit d'une fonction interne un tant soit peu plus grande pour que cette erreur soit difficile à voir. Une rigidification de la syntaxe qui permet d'éviter des erreurs (communes comme le prouve le nombre des messages de débutants sur ce sujet, la mise en garde dans le manuel...) est d'après moi parfaitement justifiée. Et puisqu'il y a deux syntaxes équivalentes (une avec match with explicite, l'autre sans), je proposais que : - la syntaxe « match with » soit réservée au filtrage de valeurs - l'on puisse utiliser des variables précédemment liées dans le filtrage de valeurs (puisqu'il n'introduit pas de nouvelles variables) - laisser le filtrage de structure tel qu'il est (et donc l'unification avec le motif, autrement dit les variables liantes) Je conçois cependant que l'on puisse ne pas être d'accord à ce sujet. Diego Olivier There are two kind of pattern matching : i) structure matching let add = function | [] -> 0 | [x] -> x | [x ; y] -> x + y | _ -> 0 ;; ii) value matching let delta = function | (0, 0, 1) -> 1 | _ -> 0 ;; mixing both allows mistakes that could be sometimes very hard to find let add = function n -> let rec addCPS = function | (total, k) when (k = 0) -> total | (k, total) -> addCPS (total + k, k - 1) ^ ^^^ in addCPS (0, n) ;; I was just proposing : - to use the « match with » syntax for value matching only - to allow the use of bounded variables in the value matching - to leave the structure match as it is of course ------------------- 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 ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Caml-list] Pattern matching 2001-11-12 9:00 ` Diego Olivier Fernandez Pons @ 2001-11-13 8:00 ` Fabrice Le Fessant 2001-11-13 23:57 ` [Caml-list] If ou Pattern-matching ? Diego Olivier Fernandez Pons 2001-11-13 16:09 ` [Caml-list] Pattern matching Luc Maranget 1 sibling, 1 reply; 16+ messages in thread From: Fabrice Le Fessant @ 2001-11-13 8:00 UTC (permalink / raw) To: Diego Olivier Fernandez Pons; +Cc: Luc Maranget, Caml [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain; charset=us-ascii, Size: 2080 bytes --] > Mon « argumentation » consiste à exhiber de mauvais programmes car je > considère qu'un « bon » langage ne doit pas laisser un mauvais > programmeur faire du mauvais code (dans la mesure du possible). Quand > je dois passer trois heures à relire le code d'une tierce personne et > que je me rends compte que l'erreur est dûe à la fonction suivante : C'est aussi faux que de dire qu'une bonne loi previent tout delit. Qu'est ce qui empechera un mauvais programmeur de croire que ton "match" sans liaison est en fait avec liaison ? Si je pousse a l'extreme, je mets un singe devant mon clavier, et j'envoie des rapports de bugs pour chaque phrase tappee que le compilateur n'accepte pas ? > I was just proposing : > - to use the « match with » syntax for value matching only > - to allow the use of bounded variables in the value matching > - to leave the structure match as it is of course Pourquoi changer ce dont tout le monde a part toi est heureux ? Tu fais du pattern-matching hyper-simple (deux a trois cas sans liaison) qui serait probablement cent fois mieux traite par un "if", et tu rales. Ce n'est pas le programmeur qui s'est plante, c'est celui qui lui a appris qu'il fallait utilise un "match" la ou il aurait du utiliser un "if". Essaie donc de faire du pattern-matching avec 30 cas (un arbre de syntaxe par exemple), et tu te rendras compte que le pattern-matching avec liaison est mille fois plus utile ! Je te vois mal ecrire l'equivalent du compilateur de ocaml avec ce pattern-matching que tu proposes... Exercice 1 d'une modification de syntaxe: prendre un code existant et le traduire dans ta syntaxe. Je te propose de jeter un oeil a typing/typecore.ml ... I was just proposing: - to use << match with >> on complex structures. - to use << if >> on simple structures where no binding is required. - to learn the semantics of a construct before using it. - Fabrice ------------------- 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 ^ permalink raw reply [flat|nested] 16+ messages in thread
* [Caml-list] If ou Pattern-matching ? 2001-11-13 8:00 ` Fabrice Le Fessant @ 2001-11-13 23:57 ` Diego Olivier Fernandez Pons 2001-11-14 10:02 ` Fabrice Le Fessant ` (2 more replies) 0 siblings, 3 replies; 16+ messages in thread From: Diego Olivier Fernandez Pons @ 2001-11-13 23:57 UTC (permalink / raw) To: fabrice.le_fessant; +Cc: Caml Je reconnais être un peu borné, j'applique en effet sans réfléchir certaines recommandations de Pierre Weis (Conseils de programmation Caml) : « On n'aura jamais peur d'abuser du filtrage ! » mais aussi « Programmer simple et clair avant tout » La question (soulevée d'ailleurs par Rémi Vanicat) est celle de l'équivalence des codes suivants : let somme = function | 0 -> 0 | k -> k + somme (k-1) ;; et let somme = function n -> if n = 0 then 0 else (k + somme (k-1)) ;; Employons donc la méthode proposée par Le Fessant : éxagérons ! let conditions = function | (0, 1, 1, 1, _) -> 1 | (1, 0, 0, _, m) -> m | (1, 1, 0, L, 0) -> 1 | (i, j, 0, L, m) when (i = j) && (L = m) -> 0 | _ -> 1 ;; (Je n'ai pas écrit 30 cas mais l'idée y était) Exercice 1 : réécrire ce code avec des « if then else » Exercice 2 : répondre à la question « lequel des deux codes est le plus lisible ? » Fabrice Le Fessant à écrit : < Tu fais du pattern-matching hyper-simple (deux a trois cas sans < liaison) qui serait probablement cent fois mieux traite par un "if", [...] < Ce n'est pas le programmeur qui s'est planté, c'est celui qui < lui a appris qu'il fallait utiliser un "match" là où il aurait dû < utiliser un "if". [...] < Essaie donc de faire du pattern-matching avec 30 cas Le filtrage est-il une alternative acceptable aux enchaînements de « if then else » ? A mon avis oui car il est nettement plus lisible, présente les informations de manière compacte et immédiatement compréhensible. Cela minimise les risques d'erreur, réduit la longueur des programmes, en facilite la maintenance, etc. Encore un extrait des excellents conseils de Weis < Au-delà d'une page, on se perd dans le code, l'indentation est peu < lisible et difficile à maintenir correcte. Le code avec filtrage que je présente assure : - une indentation uniforme (ce qui ne serait pas le cas avec des if) - une compacité qui ne nuit aucunement à la compréhension Il est vrai qu'il est plus lent (on peut regrouper des cas avec if) Les questions suivantes sont « dans quelle mesure il faut-il calquer les fonctionnalités du filtrage sur celles de "if" ? » « Comment concilier les éventuelles incompatibilités introduites ? » « Est-ce bien raisonnable ? » i) il est évident qu'on ne pourrait pas se passer du filtrage avec liaison, comment écrire sinon let longueur = function -> | [ ] -> 0 | (_ :: reste) -> 1 + longueur (reste) Cette question est donc réglée, il n'est pas question d'éliminer le filtrage avec liaison ii) quelles différences entre un filtrage et un « if then else » ? - le « if then else » permet la comparaison avec des valeurs précédemment liées - le filtrage masque les valeurs précédemment liées Proposition : - introduire une seconde version de filtrage sans liaisons qui serait identifiable par une syntaxe particulière (j'ai proposé match mais ce peut-être autre chose si cela casse du code) et permettrait la comparaison avec des valeurs précédemment liées. Critiques : - c'est compliqué à expliquer aux programmeurs (Maranget) - cela rompt l'unité conceptuelle du filtrage (Maranget) - c'est compliqué à introduire dans le compilateur (Maranget) - égalité structurelle ou égalité physique ? (Fernandez Pons) - tout le monde est heureux dans la vie sauf toi (Le Fessant) - tu serais incapable d'écrire un compilateur Caml (Le Fessant) - apprends la sémantique des constructions Caml avant de les utiliser (Le Fessant) Réponse : - cela permet d'éviter certaines constructions douteuses - le filtrage actuel fait déjà des égalités avec les constantes - les nombreux messages des débutants sur cette liste, les multiples avertissements dans le manuel montrent que la version actuelle du filtrage n'est pas si intuitive non plus Critiques : - on peut toujours obtenir du code robuste en évitant les constructions douteuses (Maranget) - on peut modifier le compilateur pour qu'il affiche un warning idoine (Maranget) Réponse : - le langage devrait aider le programmeur à coder facilement des programmes robustes et lisibles - on peut adopter une position flexible (ne pas obliger le programmeur à utiliser cette nouvelle syntaxe) Annexe : j'ai fait d'autres propositions (liaison dans le filtrage avec les variables n'apparaissant pas précédemment) mais elles introduiraient plus de difficultés qu'elles ne résolvent de problèmes. Commentaire : si la locution « pattern-matching » vous hérisse, je peux dire plutôt que je propose l'introduction d'un « multi-switch » qui serait bien utile. iii) Est-ce bien utile de faire tout ce tapage, des modifications à la sémantique du langage, etc. pour une « amélioration » aussi insignifiante et qui a plus de conséquences que je ne semble croire ? A cette question je ne puis répondre, c'est pour cela que je vous écris. Comme le signale à propos Le Fessant, je me suis jamais distingué par une connaissance approfondie du code source du compilateur Caml, ni par ma virtuosité au maniement de la sémantique du langage. Diego Olivier ------------------- 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 ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Caml-list] If ou Pattern-matching ? 2001-11-13 23:57 ` [Caml-list] If ou Pattern-matching ? Diego Olivier Fernandez Pons @ 2001-11-14 10:02 ` Fabrice Le Fessant 2001-11-14 10:47 ` Nicolas Barnier 2001-11-14 11:35 ` [Caml-list] If ou Pattern-matching ? Luc Maranget 2 siblings, 0 replies; 16+ messages in thread From: Fabrice Le Fessant @ 2001-11-14 10:02 UTC (permalink / raw) To: Diego Olivier Fernandez Pons; +Cc: Caml L'ajout d'une nouvelle construction en complement du "match" ne me semble pas indispensable, il peut suffir de rajouter un peu de sucre syntaxique pour eviter l'ecriture du "when". On peut ainsi preceder les identificateurs non liants d'un "=" dans le match, en utilisant camlp4 pour cela. Le filtrage propose par Caml n'est evidemment pas le seul possible. Il existe un bon livre de Christian Queinnec sur ce sujet (disponible gratuitement, voir "Le Filtrage" sur http://youpou.lip6.fr/queinnec/WWW/Pedagogy.html). La question est de savoir lequel est le plus adapte a la majorite des programmes, et doit donc posseder la syntaxe la plus simple... - Fabrice ------------------- 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 ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Caml-list] If ou Pattern-matching ? 2001-11-13 23:57 ` [Caml-list] If ou Pattern-matching ? Diego Olivier Fernandez Pons 2001-11-14 10:02 ` Fabrice Le Fessant @ 2001-11-14 10:47 ` Nicolas Barnier 2001-11-14 1:26 ` [Caml-list] Warnings possibles Diego Olivier Fernandez Pons 2001-11-14 11:35 ` [Caml-list] If ou Pattern-matching ? Luc Maranget 2 siblings, 1 reply; 16+ messages in thread From: Nicolas Barnier @ 2001-11-14 10:47 UTC (permalink / raw) To: Diego Olivier Fernandez Pons; +Cc: Caml On Wednesday 14 November 2001 00:57, Diego Olivier Fernandez Pons wrote: > > Je reconnais être un peu borné, j'applique en effet sans réfléchir > certaines recommandations de Pierre Weis (Conseils de programmation > Caml) : « On n'aura jamais peur d'abuser du filtrage ! » mais aussi > « Programmer simple et clair avant tout » Si si, ces deux conseils doivent s'appliquer en réfléchissant. > let somme = function n -> > if n = 0 then 0 > else (k + somme (k-1)) Pourquoi des "function" quand la fonction n'est pas définie par extension ? > Le code avec filtrage que je présente assure : > - une indentation uniforme (ce qui ne serait pas le cas avec des if) Mais si, on peut indenter de manière uniforme et structurée (si on regroupe des cas, chose que l'on fait également avec des pattern matching imbriqués) avec des if : if then else if then else if then else Tout est indenté au même niveau. > let longueur = function -> > > | [ ] -> 0 > | (_ :: reste) -> 1 + longueur (reste) > > Cette question est donc réglée, il n'est pas question d'éliminer le > filtrage avec liaison > > ii) quelles différences entre un filtrage et un « if then else » ? > - le « if then else » permet la comparaison avec des valeurs > précédemment liées > - le filtrage masque les valeurs précédemment liées Il n'y a pas de différences sémantique, c'est de la syntaxe. D'ailleurs le code suivant est très proche du précédent (mais il faut un rec et en général on évite de mettre des parenthèses autour des arguments sinon les étudiants ont du mal à comprendre le concept d'application) : let rec longueur l = if l = [] then 0 else let _ :: reste = l in 1 + longueur reste Sauf que c'est insupportable parce que ça génère un warning. De toute façon, dès qu'on doit effectuer un traitement uniforme sur une structure de données de type somme, on recopie la définition du type et on remplace les "of" par des flèches. Les listes ne font pas exception. Pour un type produit au contraire, le choix entre les deux constructions est moins immédiat - et parfois uniquement une affaire de goût, mais, vous me rétorqueriez sans doute "Chacun son mauvais goût". > Proposition : > - introduire une seconde version de filtrage sans liaisons qui > serait identifiable par une syntaxe particulière (j'ai proposé match > mais ce peut-être autre chose si cela casse du code) Ce souci de compatibilité vous honore. > et permettrait la comparaison avec des valeurs précédemment liées. > > Critiques : > - tout le monde est heureux dans la vie sauf toi (Le Fessant) > - apprends la sémantique des constructions Caml avant de les > utiliser (Le Fessant) Je dois dire que je soutiens les commentaires de Fabrice Le Fessant. > - le langage devrait aider le programmeur à coder facilement des > programmes robustes et lisibles A quel langage pensez-vous ? Personnellement, je n'en ai jamais rencontré qui permette autant que Caml d'éviter les constructions foireuses : les règles sont simples et claires, et on peut se contenter d'un sous-ensemble très cohérent du langage pour l'enseignement (e.g. obliger à mettre les "fun" ou interdire les "then" sans "else" même quand on n'effectue qu'un effet de bord). > peux dire plutôt que je propose l'introduction d'un « multi-switch » > qui serait bien utile. Ben nan parce qu'on a déjà le pattern matching. > iii) Est-ce bien utile de faire tout ce tapage, des modifications à > la sémantique du langage, etc. pour une « amélioration » aussi > insignifiante et qui a plus de conséquences que je ne semble croire ? > > A cette question je ne puis répondre, c'est pour cela que je vous > écris. Mais vous refusez d'entendre raison malgré les efforts multiples de l'équipe de développement qui a sûrement des choses importantes à faire ! Et vous faites des commentaires erronés et désobligeants : > [...] sous peine de produire un langage qui - comme Caml actuellement - ne > dépassera jamais le cadre des universitaires. On soupçonne donc un tempérament peu enclin à se laisser convaincre même par les arguments les plus rationnels et plutôt disposer à en découdre à tout prix - uniquement sur le sujet du pattern matching bien entendu. Bref votre opinion est ferme et définitive et vous n'écrivez pas pour qu'on éclaire votre lanterne. > Comme le signale à propos Le Fessant, je me suis jamais > distingué par une connaissance approfondie du code source du > compilateur Caml, ni par ma virtuosité au maniement de la sémantique > du langage. Sans commentaire. Cordialement. -- Nicolas ------------------- 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 ^ permalink raw reply [flat|nested] 16+ messages in thread
* [Caml-list] Warnings possibles 2001-11-14 10:47 ` Nicolas Barnier @ 2001-11-14 1:26 ` Diego Olivier Fernandez Pons 2001-11-14 18:24 ` Luc Maranget 0 siblings, 1 reply; 16+ messages in thread From: Diego Olivier Fernandez Pons @ 2001-11-14 1:26 UTC (permalink / raw) To: barnier; +Cc: Caml La question du filtrage semble tranchée. Essayons une proposition qui se veut constructive : - Est-il possible d'avoir un warning quand on masque une variable lors d'un filtrage ? - Est-il possible (je veux dire est-ce réalisable ? difficile ? utile ?...) de signaler que deux motifs ne sont pas exclusifs let f = function | (0,1) -> 1 | (x,1) -> x | (1,y) -> y | _ -> 1 # Attention les motifs (x,1) et (1,y) ne sont pas disjoints par exemple (1,1) Je suppose qu'il doit y avoir des problèmes liés au motif universel _ (que l'on pourrait peut-être ignorer) let f = function (x,y) -> match (x,y) with | (0,1) -> 1 | (_,1) -> x | (1,_) -> y | _ -> 1 ;; ok ! (la superposition de motifs est ignorée car on utilise _ qui est ignoré sauf pour le dernier qui assure que tous les cas sont traités) Peut-être un flag "pedantic" comme en C pour avoir ces avertissements là ? Diego Olivier ------------------- 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 ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Caml-list] Warnings possibles 2001-11-14 1:26 ` [Caml-list] Warnings possibles Diego Olivier Fernandez Pons @ 2001-11-14 18:24 ` Luc Maranget 0 siblings, 0 replies; 16+ messages in thread From: Luc Maranget @ 2001-11-14 18:24 UTC (permalink / raw) To: Diego Olivier Fernandez Pons; +Cc: barnier, Caml > > La question du filtrage semble tranchée. Essayons une proposition qui > se veut constructive : > > - Est-il possible d'avoir un warning quand on masque une variable lors > d'un filtrage ? Peut-être, fonction de la demande populaire. Il faut quand même remarquer que trop de warning tue le warning. > - Est-il possible (je veux dire est-ce réalisable ? difficile ? utile > ?...) de signaler que deux motifs ne sont pas exclusifs C'est possible et moins dur que les filtrages non-exhaustifs. Mais je ne vois pas de raison de le faire, il s'agit d'un trait reconnu du filtrage. Je ne vois pas l'intérêt de considérer que des motifs non-disjoints c'est mal. > Peut-être un flag "pedantic" comme en C pour avoir ces avertissements > là ? C'est bien là un point d'achoppement. On essaie de limiter les options. Mais dans avec l'idée de cibler l'enseignement, on pourrait effectivement le faire (pour la première suggestion). Mais avec une option -cautious (j'aime pas ``pedantic'' pas très bien connoté en français). Bon, je ne m'y mets pas demain. > > Diego Olivier --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 ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Caml-list] If ou Pattern-matching ? 2001-11-13 23:57 ` [Caml-list] If ou Pattern-matching ? Diego Olivier Fernandez Pons 2001-11-14 10:02 ` Fabrice Le Fessant 2001-11-14 10:47 ` Nicolas Barnier @ 2001-11-14 11:35 ` Luc Maranget 2 siblings, 0 replies; 16+ messages in thread From: Luc Maranget @ 2001-11-14 11:35 UTC (permalink / raw) To: Diego Olivier Fernandez Pons; +Cc: fabrice.le_fessant, Caml Je répond en bloc à tout et brièvement. Sans penser que nous (implémenteurs Caml etc.) détenons la science infuse, je crois que notre avis sur comment doit être compris un trait a un certain poids. Donc le filtrage doit être interprété comme je l'ai expliqué dans mon message précédent (prédicat ``<='' + liasons). Ce n'est pas si dur à comprendre. Le mot « sémantique » fait peut être peur, mais ça ne veut rien dire d'autre que « voilà ce que votre programme fait ». Une explication pas trop dure est de dire : voila comment votre filtrage se traduit en ``if'' et en fonction d'accès aux champs let f liste = match liste with | [] -> 0 | x::_ -> x C'est en fait : let f liste = if liste = [] then 0 else let x = car liste in x Où ``car'' est une fonction spéciale qui accède au premier champ d'une cellule de liste. NB le fait que l'on puisse définir ``car'' à l'aide du filtrage ne doit pas nous cacher que, dans le cadre de cette explication ``car'' est ``plus primitif'' que le filtrage. Votre façon de considérer le filtrage est un brin trop compliquée. Non seulement ça n'aiderait pas à concevoir le langage (mais c'est notre problème), mais ça ne vous aide pas a programmer. Maintenant, je reconnais un déficit d'explication sur ce qu'est le filtrage aux utilisateurs et en particulier aux débutants. --Luc Maranget ------------------- 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 ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Caml-list] Pattern matching 2001-11-12 9:00 ` Diego Olivier Fernandez Pons 2001-11-13 8:00 ` Fabrice Le Fessant @ 2001-11-13 16:09 ` Luc Maranget 2001-11-13 23:56 ` [Caml-list] Deux types de pattern-matching ? Diego Olivier Fernandez Pons 1 sibling, 1 reply; 16+ messages in thread From: Luc Maranget @ 2001-11-13 16:09 UTC (permalink / raw) To: Diego Olivier Fernandez Pons; +Cc: Luc Maranget, Caml Ne nous énervons pas. Comme c'est long je résume. Le problème soulevé est celui du sens des variables dans les motifs. La réponse est que ces variables sont liantes. Changer cela pose plus de problèmes que vous ne semblez le penser. Let us sum it up. The real issue is about the semantics of variables in patterns. These variables are ordinary binding occurrences. We'd better not change that. > Mon « argumentation » consiste à exhiber de mauvais programmes car je > considère qu'un « bon » langage ne doit pas laisser un mauvais > programmeur faire du mauvais code (dans la mesure du possible). Quand > je dois passer trois heures à relire le code d'une tierce personne et > que je me rends compte que l'erreur est dûe à la fonction suivante : Pouquoi pas mais le problème est également dans ce cas un problème d'apprentissage du langage et je considère que cet apprentissage est facilité par des principes simples. L'erreur classique est ici de surestimer le filtrage (pattern matching). > > let f = function n -> > let g = function > | (n, i ) -> ... > ^^ > car le programmeur a cru que n était déjà liée (l'exemple est un peu > exagéré mais bon...), j'ai tendance à taper (sans doute à tort) non > sur le programmeur mais sur le concepteur du langage. n est déjà liée, n est cachée par la nouvelle occurence liante (aka déclaration en C par ex). Ça c'est simple, ça se comprend, certes ça peu mener à des erreurs mais bon, avant de bondir « Comment ça le compilo ne fait pas ce que je veux », essayons de comprendre pourquoi il ne le fait pas. > Je vais vous dire des choses que vous n'ignorez pas au sujet du > pattern-matching, mais au moins serons nous clairs. > > Il y a deux usages du pattern-matching : > > le filtrage structurel (qui exige unification avec le motif et liaison > des variables) > let somme = function > | [] -> 0 > | [x] -> x > | [x ; y] -> x + y > | _ -> 0 > ;; > > le filtrage de valeurs qui correspond à un « if then else » en plus > compact (et sans introduction de nouvelles variables) > let delta = function > | (0, 0, 1) -> 1 > | _ -> 0 > ;; > C'est très intéressant, car le pattern matching n'a qu'une seule définition. Une présentation pédagogique inverserait, je crois, l'ordre de présentation des deux usages. Bon moi je dirait ça. Il y les listes et les paires (pour ne pas parler des arbres). Un motif est une description d'ensembles de paires, de listes, de paires de listes etc. Par exemple, (1,2) représente la paire formée de 1 et de 2. (1,_) représente toutes les paires dont la première composante est 1 [_; _] représente toutes les listes à deux elts etc. (Au passage ``_'' représente n'importe quoi). Le filtrage et bien ça marche en essayant les motifs les uns après les autres (dans l'ordre) , par exemple comme ça match x with | (1,2) -> (* ici je sais que x est la paire (1,2) *) | (1,_) -> (* ici je sais que x est la paire (1, autchose), où autchose n'est pas 2 *) | _ -> (* ici x est tout le reste *) Ce qui est merveillleux dans le filtrage c'est que je peux remplacer les ``_'' par des variables. Alors oh joie (soyons positifs) j'ai une variable qui vaut ``autchose'' dans le cas 2 ci dessus par ex match x with | (1,2) -> (* ici je sais que x est la paire (1,2) *) | (1,snd) -> je sais que snd n'est pas 2 | (fst, snd) -> ... Voilà c'est tout. (on peut ici comparer une copie de liste en lisp et en ML si on veut) (if (consp l) (cons (car l) (copy (cdr l))) ()) let rec copy l = match l with | x::rem -> x::copy rem | [] -> [] Théorisons un peut (terrorisons ?). Bon, chouette mais comment définir ces fameux ensembles de valeurs représentées par des motifs. Bon, toujours avec les paires et les listes. Je vais definir une relation dite de filtrage (notée <=) comme ça : _ <= V (``_'' filtre toutes les valeurs *) [] <= [] (* le motif [] filtre la liste vide) n <= n (* le motif ``n'' (un entier) filtre la valeur entière n *) (* Tout ça passe aux arguments *) (p1, p2) <= (V1, V2) ssi p1 <= V1 et p2 <= V2 p1 :: p2 <= V1 :: V2 En plus je peux, partout ou on met ``_'' aussi mettre des variables. Alors ces variables sont liées aux sous composants correspondants. On peut (pourvu que la même variable ne se répète pas) calculer ces liaisons comme ça : Liasons (x, V) = [x, V] Liasons ( (p1, p2), (V1, V2)) = Liaisons (p1, V1) |_| Liaisons (p2, V2) ^^^^ Union. Etc... Bon évidemment, si la même variable est présente (par ex dans p1 et p2 ci-dessus), ya un blème. On peut le résoudre soit 1. En rendant cette situation illégale. 2. En obligeant les deux valeurs liées à être égales. En Caml c'est ``1.'' qui est choisi. Paske Le sens d'être égal n'est pas clair (égal structurel, qui peut boucler) ou egal physique (qui peut echouer). > Ce dont je me « plains » est que la syntaxe actuelle de OCaml ne > différencie pas clairement les deux et permet des mélanges qui peuvent > donner lieu à du code douteux, à des erreurs difficiles à détecter... Ben non, pour moi il y a un seul filtrage, pas deux. Pour les erreurs, vous avez raison, mais elle proviennent plutôt d'une méconnaissance de ce qu'est réellement le filtrage. La solution ``protectrice'' serait tout simplement d'interdire de cacher une variable en introduisant une variable homonyme dans un motif. Votre position (estimable) est je crois de changer le sens du filtrage pour y ajouter plus d'expressivité (de fait des égalités en plus). Il y a deux niveaux 1. Égalité entre deux variables du même motif. 2. Égalité entre une variable d'un motif et une autre liée au préalable. Je pense que votre combat est perdu d'avance, car c'est en fait compliqué et l'utilisateur peut expliciter facilement ces égalités quand il en a besoin. Je ne peux pas m'empêcher d'attirer votre attention sur ce que, si ces changements (bon le no 2, le no 1 ne pose pas ce pb) rendent correct (ie, conforme à ce que vous croyiez qu'il signifiait) le programme de votre ami ; il rendront incorrects d'autres programmes écrits par les (nombreux) utilisateurs qui ont la même vue du filtrage et de la liaison statique que moi. --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 ^ permalink raw reply [flat|nested] 16+ messages in thread
* [Caml-list] Deux types de pattern-matching ? 2001-11-13 16:09 ` [Caml-list] Pattern matching Luc Maranget @ 2001-11-13 23:56 ` Diego Olivier Fernandez Pons 2001-11-14 10:19 ` [Caml-list] " Luc Maranget 0 siblings, 1 reply; 16+ messages in thread From: Diego Olivier Fernandez Pons @ 2001-11-13 23:56 UTC (permalink / raw) To: Luc Maranget; +Cc: Caml < C'est très intéressant, car le pattern matching n'a qu'une seule < définition. Je ne suis pas informaticien de formation, encore moins spécialiste de la sémantique des langages. Mon approche pour cette raison est purement pragmatique : let valeur = function | (1,2) -> 0 | (1, snd) -> snd | (fst, snd) -> fst Filtrage par valeurs : on peut transformer en « if then else » let valeurs = function (x, y) -> if (x = 1) && (y = 2) then 1 else if (x = 1) then y else x ;; De même le code suivant let valeur = function | [ ] -> 0 | [1; 3] -> 1 | _ -> 2 Par contre let structure = function | [ ] -> 0 | [x; 1] -> x | _ -> 2 ;; on ne peut pas transformer en « if then else » seul, il faut utiliser un let destructurant (pour faire l'unification) let structure = function liste -> if (liste = [ ]) then 0 else let (x :: reste) = liste in if (reste = [1]) then x else 2 ;; Pour moi un code comme : match couple with | (0, 1) -> 0 | (1, y) -> y | (x, y) -> x commence par destructurer couple puis fait un filtrage de valeurs let (x,y) = couple in match (x,y) with | (0,1) -> 0 | (1, _) -> y | (_, _) -> x Une seule liaison des variables x et y puis comparaisons (les unifications multiples ne se justifient pas) C'est d'ailleurs ce que fait la définition d'une fonction let valeurs = function (x,y) -> [...] let valeurs = function couple -> let (x,y) = couple in [...] Autrement dit, je décompose le filtrage de motif en deux opérations élémentaires : i) l'unification ii) disjonction de cas Ce qui donne 3 « types » de filtrages - disjonction de cas (éventuellement précédée d'une unification) - unification (éventuellement suivie d'une disjonction) - mélange des deux Je proscris pour les raisons déjà expliquées le mélange (risques d'erreur liées aux variables muettes...) et recommande au lieu l'enchaînement des deux opérations élémentaires Bien sûr, formellement le code suivant match liste with | [x; 1] -> x est équivalent à une disjonction de cas infinie ... | [0; 1] -> 0 | [1; 1] -> 1 | [2; 1] -> 2 ... Ce qui en ferait un filtrage de structure serait l'utilisation dans le second membre d'un motif interne au premier membre, cela dit let valeur = function | [ ] -> 0 | [ _ ; 1] -> 1 | _ ->2 ne peut pas se transformer en « if then else » sans unification et n'utilise pas de motif interne au premier membre ce qui finit d'achever la séparation des deux notions : d'un point de vue théorique elle est parfaitement vaseuse. De toutes les façons, vous ne pouvez pas demander aux utilisateurs d'un langage de comprendre parfaitement les fondements théoriques de celui-ci pour l'utiliser correctement, sous peine de produire un langage qui - comme Caml actuellement - ne dépassera jamais le cadre des universitaires. Il faut résoudre un certain nombre de problèmes pragmatiques liés à l'usage, et les erreurs (nombreuses) liées au pattern matching en sont un. Diego Olivier ------------------- 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 ^ permalink raw reply [flat|nested] 16+ messages in thread
* [Caml-list] Re: Deux types de pattern-matching ? 2001-11-13 23:56 ` [Caml-list] Deux types de pattern-matching ? Diego Olivier Fernandez Pons @ 2001-11-14 10:19 ` Luc Maranget 0 siblings, 0 replies; 16+ messages in thread From: Luc Maranget @ 2001-11-14 10:19 UTC (permalink / raw) To: Diego Olivier Fernandez Pons; +Cc: Luc Maranget, Caml > > < C'est très intéressant, car le pattern matching n'a qu'une seule > < définition. > > Je ne suis pas informaticien de formation, encore moins spécialiste de > la sémantique des langages. Mon approche pour cette raison est > purement pragmatique : Bon j'en ai rajouté. Mais mon point reste de proposer une vue simple et uniforme du filtrage. Nul besoin d'être spécialiste de la sémantique, je vais essayer un point de vue de compilation de Caml dans lui même. > > let structure = function > | [ ] -> 0 > | [x; 1] -> x > | _ -> 2 > ;; > > on ne peut pas transformer en « if then else » seul, il faut > utiliser un let destructurant (pour faire l'unification) > Ben c'est pas comme ça que je présenterais les choses > let structure = function liste -> > if (liste = [ ]) then 0 > else > let (x :: reste) = liste in > if (reste = [1]) then x else 2 > ;; Ça ne résoud pas le pb du pt de vue de la compilation, car il reste un filtrage. Supposons en plis du if, données deux fonctions ``car'' et ``cdr'' (qui sont en fait de facons plus génerales des fonction d'accès aux champs d'une cellule de liste, ie des accès indexés) car x est (getfield 0 x) Alors la compilation de structure est let structure = function liste -> if (liste = [ ]) then 0 else let x = car x and reste = cdr list in if (reste = []) then 2 else let tmp1 = car reste and tmp2 = cdr reste in if tmp1 = 1 then if tmp2 = [] then x else 2 else 2 > > Pour moi un code comme : > > match couple with > | (0, 1) -> 0 > | (1, y) -> y > | (x, y) -> x > > commence par destructurer couple puis fait un filtrage de valeurs > > let (x,y) = couple in > match (x,y) with > | (0,1) -> 0 > | (1, _) -> y > | (_, _) -> x > > Une seule liaison des variables x et y puis comparaisons (les > unifications multiples ne se justifient pas) > C'est d'ailleurs ce que fait la définition d'une fonction > > let valeurs = function (x,y) -> [...] > let valeurs = function couple -> let (x,y) = couple in [...] > > Autrement dit, je décompose le filtrage de motif en deux opérations > élémentaires : > i) l'unification > ii) disjonction de cas Non c'est, filtrage (et non pas unification, c'est pas pareil) avec liasons éventuelle de variables des variables des filtres aux champs correspondants des valeurs filtrées. J'ai l'air d'un vieux chouf, mais je crois que c'est comme ça qu'on comprend le mieux. > > Je proscris pour les raisons déjà expliquées le mélange (risques > d'erreur liées aux variables muettes...) et recommande au lieu > l'enchaînement des deux opérations élémentaires > > Bien sûr, formellement le code suivant > match liste with > | [x; 1] -> x > est équivalent à une disjonction de cas infinie > ... > | [0; 1] -> 0 > | [1; 1] -> 1 > | [2; 1] -> 2 > ... Non. La définition complète du filtrage (reporter vous au prédicat ``<='' du message précédent) n'a pas besoin de ce truc pour définir le filtrage par un motif contenant une variable. (Même si en un sens l'équivalence est valide, mais elle n'aide pas à comprendre ce qui se passe. au niveaux élémentaire un filtre ``_::_'' est équivalent au prédicat ``c'est un cons'' (consp en lisp). > Ce qui en ferait un filtrage de structure serait l'utilisation dans le > second membre d'un motif interne au premier membre, cela dit > > let valeur = function > | [ ] -> 0 > | [ _ ; 1] -> 1 > | _ ->2 > > ne peut pas se transformer en « if then else » sans unification et > n'utilise pas de motif interne au premier membre ce qui finit > d'achever la séparation des deux notions : d'un point de vue > théorique elle est parfaitement vaseuse. > > De toutes les façons, vous ne pouvez pas demander aux utilisateurs > d'un langage de comprendre parfaitement les fondements théoriques de > celui-ci pour l'utiliser correctement, sous peine de produire un > langage qui - comme Caml actuellement - ne dépassera jamais le cadre > des universitaires. Il faut résoudre un certain nombre de problèmes > pragmatiques liés à l'usage, et les erreurs (nombreuses) liées au > pattern matching en sont un. > C'est bien le problème. Pour avoir un langage de programmation pas trop bizarre, un peu de théorie ne nuit jamais. La « théorie » n'est pas le mal, n'est pas hors de portée. Je ne crois pas que l'on puisse réellement programmer en utlisant le filtrage, sans tout à fait comprendre ce qui se passe. prenons un exemple extrêment simple qui évite les motifs trop compliqués (c'est aussi un pb) let f liste = match l with | [] -> 0 | x::_ -> x c'est let f liste = if liste = [] then 0 else > Diego Olivier > > > > > > ------------------- 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 ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2001-11-14 18:24 UTC | newest] Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2001-11-08 2:33 [Caml-list] Pattern matching Diego Olivier Fernandez Pons 2001-11-09 0:26 ` Pixel 2001-11-09 10:59 ` Luc Maranget [not found] ` <15339.34220.198731.791811@lachesis.inria.fr> 2001-11-10 2:16 ` Diego Olivier Fernandez Pons 2001-11-12 10:29 ` Luc Maranget 2001-11-12 9:00 ` Diego Olivier Fernandez Pons 2001-11-13 8:00 ` Fabrice Le Fessant 2001-11-13 23:57 ` [Caml-list] If ou Pattern-matching ? Diego Olivier Fernandez Pons 2001-11-14 10:02 ` Fabrice Le Fessant 2001-11-14 10:47 ` Nicolas Barnier 2001-11-14 1:26 ` [Caml-list] Warnings possibles Diego Olivier Fernandez Pons 2001-11-14 18:24 ` Luc Maranget 2001-11-14 11:35 ` [Caml-list] If ou Pattern-matching ? Luc Maranget 2001-11-13 16:09 ` [Caml-list] Pattern matching Luc Maranget 2001-11-13 23:56 ` [Caml-list] Deux types de pattern-matching ? Diego Olivier Fernandez Pons 2001-11-14 10:19 ` [Caml-list] " Luc Maranget
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox