Re: [q-lang-users] "listof" surprises
Brought to you by:
agraef
From: Albert G. <Dr....@t-...> - 2007-05-15 08:21:11
|
Marco Maggesi wrote: > Ok. But > > ==> case (1,2) ((1,2),3) > ! Exception > syserr 8 > >>> case (1,2) ((1,2),3) > ^ It's not a bug, it's a feature. ;-) What's maybe confuding for Haskell programmers here is that 'case' is really just an ordinary Q function (albeit a special form) and the clauses argument is just a tuple. For instance, your first example: ==> case (1,2) ((1,2),3; _, foo) 3 is just a shortcut for: ==> case (1,2) (((1,2),3), (_, foo)) 3 Note that the notation used in the first example is "grouping syntax", see the end of sec. 6.3 in the manual [http://q-lang.sourceforge.net/qdoc/qdoc_6.html#SEC14] for an explanation. This works with all kinds of tuple values (and also with lists and streams): ==> (1,2;3,4,5;6,7) ((1,2),(3,4,5),(6,7)) So 'case (1,2) ((1,2),3)' is really just the same as 'case (1,2) (1,2;3)', which is most probably *not* what you wanted. You probably wanted this: ==> case (1,2) ((1,2),3;) 3 Note that '((1,2),3;)' is just a shortcut for the 1-tuple '(((1,2),3),)' here. > I discovered this bug while trying to use 'case' to mimimc a common > pattern used in other functional languages, namely, use 'let .. in ..' > to destroy data with irrefutable pattern matching. E.g., say z1, z2 > are complex numbers and you want to computer their sum. Then in ML > or Haskell you can write something like: > > let (x1,y1) = z1 in > let (x2,y2) = z2 in > (x1+x2, y1+y2); Well, you can do pretty much the same with Q's 'where' clauses, like: foo Z1 Z2 = (X1+X2,Y1+Y2) where (X1,Y1) = Z1, (X2,Y2) = Z2; Or you could use 'case', as you intended, which has the advantage that you can use it anywhere inside an expression and don't need an equation to do the binding. You could even define yourself a special form 'let' as follows: special let B X; let (A=Z) X = case Z (A,X;); Example: ==> let ((1,X)=(1,2)) (X+1) 3 Or you could define 'let' using 'lambda': let (A=Z) X = (\A.X) Z; The difference is that the first definition of 'let' will cause an exception to be raised for a refuted match, while the second definition just yields an unevaluated lambda application in this case. (Note that, in any case, a pattern like (X,Y) is *never* going to be irrefutable in Q, because of the dynamic typing.) You see, Q is rather different from Haskell and most other FPLs in that stuff like 'case', 'lambda' etc. is *not* built into the language, but is defined *on top* of the term rewriting calculus which is the basis of Q. (Well, actually 'lambda' is provided as a builtin now, but that's just for performance reasons, otherwise it's just an ordinary Q function. In fact, 'lambda' was defined in the standard library in versions <7.x of the interpreter.) HTH, Albert -- Dr. Albert Gr"af Dept. of Music-Informatics, University of Mainz, Germany Email: Dr....@t-..., ag...@mu... WWW: http://www.musikinformatik.uni-mainz.de/ag |