From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on yquem.inria.fr X-Spam-Level: X-Spam-Status: No, score=0.9 required=5.0 tests=AWL,SPF_NEUTRAL autolearn=disabled version=3.1.3 Received: from concorde.inria.fr (concorde.inria.fr [192.93.2.39]) by yquem.inria.fr (Postfix) with ESMTP id 2D5EFBC6B for ; Sat, 30 Jun 2007 06:44:19 +0200 (CEST) Received: from ug-out-1314.google.com (ug-out-1314.google.com [66.249.92.170]) by concorde.inria.fr (8.13.6/8.13.6) with ESMTP id l5U4iIJI001442 for ; Sat, 30 Jun 2007 06:44:18 +0200 Received: by ug-out-1314.google.com with SMTP id o2so868011uge for ; Fri, 29 Jun 2007 21:44:18 -0700 (PDT) DKIM-Signature: a=rsa-sha1; c=relaxed/relaxed; d=gmail.com; s=beta; h=domainkey-signature:received:received:message-id:date:from:user-agent:mime-version:to:subject:references:in-reply-to:content-type:content-transfer-encoding:sender; b=hmUA4l5ubq5aa+yfuN0RBHeN5cgxv5ayCmCgAdK0jn5eA2B4qdAu0qPuDifUguexWHM2FGZvXNdbqMI0ntE4G0yAnSI7etfBBhsYJCHfJ2DExSRfQiTq1+IVVMTyDalHGXV+WtX6XwFRa+pkVcoYahkZHmMvR1+yCf3+rrlKBFs= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=beta; h=received:message-id:date:from:user-agent:mime-version:to:subject:references:in-reply-to:content-type:content-transfer-encoding:sender; b=RP2WAchEKf3PMdze8jQ+BRyhQwnc6Zxyy3Zw56IZewRqClLBYPZDXVXYqZEuORhsrsgwu30zqaENEduQbs+1CmTNUCqZTLOQrtHU1mHpfajGJ0y0opOWDqlpqkirK1hssiIY08MY4dJqnpNVk1LQiEqfTMzhsPJQqiQ4nIyprco= Received: by 10.67.101.10 with SMTP id d10mr2471472ugm.1183178658293; Fri, 29 Jun 2007 21:44:18 -0700 (PDT) Received: from ?192.168.0.6? ( [87.88.165.197]) by mx.google.com with ESMTP id u9sm29124227muf.2007.06.29.21.44.16 (version=SSLv3 cipher=RC4-MD5); Fri, 29 Jun 2007 21:44:16 -0700 (PDT) Message-ID: <4685DFA0.7000306@lix.polytechnique.fr> Date: Sat, 30 Jun 2007 06:44:16 +0200 From: Arnaud Spiwack User-Agent: Thunderbird 2.0.0.4 (Windows/20070604) MIME-Version: 1.0 To: Caml List Subject: Re: [Caml-list] ANN: pattern guards References: <1183141562.5305.19.camel@rosella.wigram> <468555F9.7090005@ed.ac.uk> <1183176563.8849.27.camel@rosella.wigram> In-Reply-To: <1183176563.8849.27.camel@rosella.wigram> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit Sender: Arnaud Spiwack X-Miltered: at concorde with ID 4685DFA2.002 by Joe's j-chkmail (http://j-chkmail . ensmp . fr)! X-Spam: no; 0.00; lix:01 variants:01 0100,:01 0100,:01 ocaml:01 bindings:01 syntax:01 syntax:01 'when':01 'when':01 conceptually:01 function':01 'with:98 'with:98 compromising:98 A (too) quick answer could of course be: "in the absence of a 'with clause', it is considered the identity 'with clause'". But I'm not sure it's that satisfying in practice. (it precisely and accurately adresses this very case John Skaller is raising, but not the same example with an additional variable in each constructor...). A suitable solution for nested guarded patterns could be, instead of saying "all the branches of the or-pattern must agree on the variable", to use a less coercive, but more compromising law : "only the variable common in all the branches of the or-pattern are bound in the match branch". This sentence uses "branch" far too many times, which makes it awkward and slighlty evil, but the principle is there : function | A x | B t -> %1 Would bind nothing in %1, but still be legal (should raise "unused variable" warnings though). More interestingly : function | C x with z=3 and w=2*x | D z r s v with w = r+s+v -> %2 Would bind z and w only in %2 (without "unused variable" warning this time, provided %2 contains z and w). At the moment I'm writing this mail, it sounds like a safe way to proceed. And to be resemble what Jeremy Yallop was suggesting in his last mail as well. PS : Slight variants this solution, which I would consider messier myself, would be to say that "only the with -clause pattern variables are considered bound in the branch body", as Skaller suggested. And that an identity with clause is added "each time it is necessary for the branch body" (though this is not clear in case of naming conflict) or "each time is is necessary for all the branches to have the same set of variables" (plus the "no with is all identities" thingy) which may be safe as well (but the original one sounds more flexible). Arnaud Spiwack skaller a écrit : > On Fri, 2007-06-29 at 19:56 +0100, Jeremy Yallop wrote: > >> skaller wrote: >> >>> On Fri, 2007-06-29 at 15:19 +0100, Jeremy Yallop wrote: >>> >>>> I'm pleased to announce the initial release of `patterns', an OCaml >>>> extension providing general-purposes additions to pattern matching. >>>> >>> I want to do this: >>> >>> match x with >>> | Y x with a=x and b=x >>> | X (y,z) with a=y and b=z >>> -> f a b >>> >> Interesting. Do you want 'z' to be in scope in the guards ("a=y" etc.) >> but not in the expression ("f a b")? Or do you just generally want to >> allow or-patterns where the branches have different bindings as long as >> the expression only uses variables that are bound in every branch? >> > > Good question. I don't know. In theory, the idea is a > 'change of variables' as in a coordinate transformation, so only the > 'final' variables should be in scope, i.e. 'z' would not be in scope. > > In practice, a suitable syntax needs to be devised which is convenient > to use: a common case would be: > > | X with x = 1 > | Y x -> f x > > and it would be messy to have to write the identity change of variables > in the second branch.. so I'm open to suggestions as to syntax. > > >>> This won't work at the moment for two reasons: >>> >>> * I assume the precedence of 'with' is the same as 'when', >>> which is not convenient >>> >> Right: "with" scopes over an entire match-case, which might include >> or-patterns, just as with "when". >> > > Which is a pain, you can't write: > > ( > | X > | Y x when f x > | Z x when g x > ) > -> .... > > [Felix allows nested 'when' clauses but not alternatives .. the latter > due to laziness on my part implementing it] > > >>> * the variables in the basic patterns don't agree >>> >>> The whole point of the above is to switch all the branches >>> to normalised variables. At the moment I have to write: >>> >>> match x with >>> | Y x -> f x x >>> | X (y,z) -> f y z >>> >> Unless I'm mistaken you can write this as >> >> match x with >> | Y (y as z) >> | X (y,z) -> f y z >> >> Is there some more general case for which this won't work out? >> > > Of course! See above. Conceptually you need an arbitrary > change of variables. For example: > > | Polar (r, theta) with z = polar r theta > | Cartesian (x,y) with z = cartesian x y > -> f z > > As far as I can see this is basically eta-expansion, > known to dummies like me as a 'wrapper function', > which for functions allows you call a function with one > set of variables with a completely different set of variables > by a standard change of variables > > The idea is basically that, but 'moved' to the other > side of the -> sign in a pattern match. The above case > can of course be written: > > | Polar (r, theta) -> let z = polar r theta in f z > | Cartestian (x,y) -> let z = cartesian x y in f z > > but involves duplicating the call to f. > > BTW: I'm writing some basic Scheme at the moment and I'm struck > by how much is lost, not having pattern matching -- yet > of course it is almost all just sugar. > > BTW2: It also strikes me good syntactic design is a tradeoff > between the tensions of avoiding duplication and gratuitous > invention, retaining localisation (things should be > defined near where they're used), and modularity > (name anything complex). > > So for example simple anonymous functions are good > (localisation), let/in is good (factor complexity > but retain localisation) and C++ sucks (loss of > localisation). > >