q-lang-users Mailing List for Q - Equational Programming Language (Page 22)
Brought to you by:
agraef
You can subscribe to this list here.
2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2004 |
Jan
(3) |
Feb
(27) |
Mar
|
Apr
(4) |
May
(11) |
Jun
(5) |
Jul
(5) |
Aug
(6) |
Sep
(15) |
Oct
(28) |
Nov
(8) |
Dec
|
2005 |
Jan
(9) |
Feb
(5) |
Mar
(10) |
Apr
(43) |
May
(8) |
Jun
(31) |
Jul
(45) |
Aug
(17) |
Sep
(8) |
Oct
(30) |
Nov
(2) |
Dec
(6) |
2006 |
Jan
(4) |
Feb
(20) |
Mar
(1) |
Apr
|
May
(92) |
Jun
(179) |
Jul
(26) |
Aug
(65) |
Sep
(36) |
Oct
(38) |
Nov
(44) |
Dec
(68) |
2007 |
Jan
(11) |
Feb
(25) |
Mar
(37) |
Apr
(7) |
May
(83) |
Jun
(77) |
Jul
(44) |
Aug
(4) |
Sep
(28) |
Oct
(53) |
Nov
(12) |
Dec
(21) |
2008 |
Jan
(66) |
Feb
(45) |
Mar
(30) |
Apr
(50) |
May
(9) |
Jun
(18) |
Jul
(11) |
Aug
(6) |
Sep
(4) |
Oct
|
Nov
|
Dec
|
2009 |
Jan
|
Feb
|
Mar
|
Apr
(3) |
May
(2) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2010 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
|
Dec
|
From: Keith T. <kaz...@ea...> - 2007-05-25 09:42:49
|
Hello Albert -- --- Albert Graef <Dr....@t-...> writes: - In Q this definition can now be written as follows: - clunky ENV VAR1 VAR1 - where just VAL1 = lookup ENV VAR1, - just VAL2 = lookup ENV VAR2: <<<<< Is that colon ':' following 'VAR2' correct? It doesn't look right, but I know that I have probably missed something along the way... (so I'm asking you nicely for clarification =). --- Albert Graef <Dr....@t-...> writes: - Another side note, and request for comments about "qualifier" vs. "guard" [snip!] Wrt. "simple" labels, e.g., "qualifier" and "guard", if "guard" is already established, then why not go with it? Unless, of course, Q has a special use for "guard"; but it means the same, right? Similarly, wrt. "guarded equations" and "conditional equations", the former expression is better for folks coming to Q from Haskell (over on perl6lang, they claim that before Pugs*, that there were only *two* people programming in Haskell... ;-). OTOH, I think that introducing the concept of "conditional equations" is also appropriate, if we first note that this is how term rewriting refers to "guarded equations". Travel and an expanded vocabulary both serve to broaden the mind! Just my two cents! =) Cheers, Keith *Pugs = Perl Users Gofer System (or so I think...) |
From: Albert G. <Dr....@t-...> - 2007-05-25 09:07:49
|
Keith Trenton wrote: > Cool. OTOH, I'm still waiting for syntax to support the new 'when' and 'what if' clauses... LOL. I guess that we'll get those when the first 64 qubit quantum computers arrive. ;-) More seriously, the Haskell programmers among you probably noted that the new syntax looks almost like Haskell's guarded equations (including Peyton-Jones' pattern guards), except that it's a tad more verbose (and, of course, in Q the qualifiers are processed from right to left rather than from left to right). E.g., here's the example taken from http://research.microsoft.com/~simonpj/Haskell/guards.html: clunky env var1 var1 | Just val1 <- lookup env var1 , Just val2 <- lookup env var2 = val1 + val2 ...other equations for clunky... In Q this definition can now be written as follows: clunky ENV VAR1 VAR1 where just VAL1 = lookup ENV VAR1, just VAL2 = lookup ENV VAR2: = VAL1 + VAL2; ...other equations for clunky... (Of course you could already define 'clunky' that way with a rhs qualifier ever since Q got its 'where' clauses, but the new syntax matches Haskell's more closely.) All in all, I think that the new syntax looks pretty nice, and the ability to mix lhs with rhs qualifiers allows you to handle the most common usage cases without having to resort to some kind of nested "case structures" which tend to be harder to read (YMMV, of course). -- Another side note, and request for comments about "qualifier" vs. "guard": AFAICS, the term "qualifier", which I use as an umbrella term for both 'if' and 'where' clauses, is one of the few remaining original "Q'isms" in the manual. Maybe the term "guard" would be more common/appropriate there? And should I better use "guarded equations" instead of "conditional equations"? (This latter term actually comes from term rewriting theory, so it's not my invention.) Yes, I'm old enough to still remember the fate of Algol 68 whose designers made up all kinds of weird names for common things. ;-) Of course, mathematicians tend to invent their own jargon as they need it, but I realize that if there's a well-established term for a certain notion then it should be used to avoid confusion. Cheers, 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 |
From: Keith T. <kaz...@ea...> - 2007-05-25 03:00:21
|
Hello Albert -- --- Albert Graef <Dr....@t-...> writes: - Ok, I've finally given in to popular demand and added a syntax - for shared 'if' and 'where' clauses. ;-) Cool. OTOH, I'm still waiting for syntax to support the new 'when' and 'what if' clauses... ... ... ... Just kidding! ;-D Cheers! Keith |
From: Albert G. <Dr....@t-...> - 2007-05-25 00:45:22
|
Hi all, Ok, I've finally given in to popular demand and added a syntax for shared 'if' and 'where' clauses. ;-) It's based on the idea of placing the guards on the lhs of an equation which, IIRC, was first suggested by Eddie, but the solution I implemented is more general in that it allows arbitrary collections of 'if's and 'where's to be placed on the lhs of an equation. This is in cvs now, but not documented in the manual yet, and also needs some more testing, so please report bugs asap. Here's the scoop from the NEWS file: There's a new syntax for guards ('if' and 'where' clauses) which may be shared by different equations for the same left-hand side. The new kind of guards is written on the left-hand side of an equation, like so: fact N if N>0: = N*fact (N-1); otherwise: = 1; The lhs guards work exactly like the "old-style" guards which are written on the right-hand side, at the end of an equation, but while the latter are always confined to a single equation, the former have a scope which extends up to the next equation with either another lhs guard or an explicit left-hand side. Conditions and local variable bindings are then shared between all equations in the scope of the guard. Of course, lhs guards can be freely mixed with rhs guards. For instance: strip C S where N = #S-1 if not null S: = strip C $ sub S 0 (N-1) if S!N = C; = strip C $ sub S 1 N if S!0 = C; otherwise: = S; Here, the scope of the condition 'not null S' and the local definition 'N = #S-1' encompasses the first two equations. Enjoy! :) 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 |
From: Albert G. <Dr....@t-...> - 2007-05-19 13:32:00
|
Marco Maggesi wrote: > Sorry for asking something that was clearly stated in the manual. No problem, the manual is big and I'm aware that not everyone will read it from cover to cover before starting to explore the more advanced parts of Q. Also, I must admit that the description of this relatively new feature in the manual is somewhat obscure and not illustrated well enough right now. 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 |
From: Marco M. <ma...@ma...> - 2007-05-19 10:49:25
|
On May 17, 2007, at 10:11 PM, Albert Graef wrote: > Hi Marco, > > again, it's a feature, not a bug. Please refer to Section 9.2 [Special > Constructors] of the manual for an explanation: > http://q-lang.sourceforge.net/qdoc/qdoc_9.html#SEC44 Ok, thank you for the explanation. Sorry for asking something that was clearly stated in the manual. M. |
From: Albert G. <Dr....@t-...> - 2007-05-19 10:38:40
|
/me wrote: > Unfortunately, the above won't work yet if you define 'let' in terms of > 'case', because 'case' expressions aren't an instance of 'Lambda' right > now. Should they be? Probably. Another item for the Q 7.7 TODO list... Ok, this is fixed now. Thus the following alternative definition of 'let' will now work as expected: type Let : Lambda = special let B X; let (A=Z) X = case Z (A,X;); lambdax (let (A=Z) X) = '(case Z (A,X;)); As a bonus, I've also added two special forms 'condfun' and 'casefun' which allow you to create conditional and pattern-matching abstractions, which take their data as the second parameter. I.e., 'casefun' is just 'case' with its arguments reversed, which provides you with a means to quickly define an anonymous p.-m. function, e.g.: ==> casefun ((X,Y),X*Y;X,X) (2,3) 6 Similarly, 'condfun' applies the predicate P from each branch (P,X) to the extra parameter Y and, if it yields true, returns the corresponding X Y. For instance, here's a rather contrived way to describe the sign function: ==> condfun ((>0),cst 1;(<0),cst (-1);(=0),cst 0) 0 0 In fact, both 'case' and 'casefun' are now instances of 'Lambda' which just expand to an equivalent 'condfun' expression. Cheers, 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 |
From: Albert G. <Dr....@t-...> - 2007-05-18 13:30:37
|
Ok, I just committed the necessary changes to implemented _FAIL_, but I still need a nice and useful example of _FAIL_ for the documentation. Any ideas? About the name: I sticked to '_FAIL_' after all. I know that it sticks out like a sore thumb, but that's actually intended. :-) Alexander Nickolsky wrote: > I mean 'fail' acts as if the current rule's left side did not match. > _FAIL_ is a regular function. Note that 'fail' is a "regular function", too. In fact, if you take a look at the latest cvs sources you'll see that both fail and _FAIL_ are implemented in a completely analogous fashion. They both just signal a special kind of exception which is then handled in the guts of the interpreter by aborting either just the current equation or all remaining equations, respectively. 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 |
From: Alexander N. <AN...@sp...> - 2007-05-18 04:56:09
|
Hello Albert, Friday, May 18, 2007, 12:52:10 AM, you wrote: AG> Alexander Nickolsky wrote: >> len [] = 0; >> len [[H|Hs]|T] = _FAIL_; >> len [H|T] = 1+len T; >> >> so semantics of _FAIL_ would be : rewrite the current match with >> itself and return. >> So, 'fail' applies to the left side, but _FAIL_ applies to the right side. AG> I don't grok this last sentence. Should 'len [[1,2],3]' return 'len AG> [[1,2],3]' itself, or _FAIL_, or what? And what should 'len [1,[2,3]]' AG> return? I mean 'fail' acts as if the current rule's left side did not match. _FAIL_ is a regular function. I think 'len [[1,2],3]' should return 'len [[1,2],3]'. As it has been already mentioned, () is a great no-value designator. -- Best regards, Alexander mailto:AN...@sp... |
From: Albert G. <Dr....@t-...> - 2007-05-17 20:46:31
|
Alexander Nickolsky wrote: > len [] = 0; > len [[H|Hs]|T] = _FAIL_; > len [H|T] = 1+len T; > > so semantics of _FAIL_ would be : rewrite the current match with > itself and return. > So, 'fail' applies to the left side, but _FAIL_ applies to the right side. I don't grok this last sentence. Should 'len [[1,2],3]' return 'len [[1,2],3]' itself, or _FAIL_, or what? And what should 'len [1,[2,3]]' return? > no matter how you call it - reject, normal, agree, refuse - which > strangely means the same. reject sounds like a worthy candidate. Or we could just use _FAIL_, it's a valid function identifier. > X+Y = Y+X; // commutative rule > will not work. No, it just loops. In a CAS, you'd have to add a qualifying condition there which makes sure that terms are ordered in some way. 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 |
From: John C. <co...@cc...> - 2007-05-17 20:42:50
|
Albert Graef scripsit: > So, John, what do you think about the "super fail" operation? Useful? > Harmful? Don't care? I think it's probably useful. > There are some arguments against adding such a facility, but then again > the limited-scope 'fail' we have now and exceptions aren't exactly part > of standard term rewriting either, but are quite useful, too. Indeed. -- John Cowan http://www.ccil.org/~cowan <co...@cc...> You tollerday donsk? N. You tolkatiff scowegian? Nn. You spigotty anglease? Nnn. You phonio saxo? Nnnn. Clear all so! `Tis a Jute.... (Finnegans Wake 16.5) |
From: Albert G. <Dr....@t-...> - 2007-05-17 20:18:54
|
John Cowan wrote: > Post in haste, repent at leisure, that's me. I have to remember that quote, next time when I'm guilty of this. ;-) So, John, what do you think about the "super fail" operation? Useful? Harmful? Don't care? There are some arguments against adding such a facility, but then again the limited-scope 'fail' we have now and exceptions aren't exactly part of standard term rewriting either, but are quite useful, too. 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 |
From: Albert G. <Dr....@t-...> - 2007-05-17 20:05:02
|
Hi Marco, again, it's a feature, not a bug. Please refer to Section 9.2 [Special Constructors] of the manual for an explanation: http://q-lang.sourceforge.net/qdoc/qdoc_9.html#SEC44 Quote: "Pattern matching on non-special arguments of a function takes into account embedded special data constructors and will automagically evaluate deferred subterms as needed." This "call-by-need" pattern matching works pretty much like in Haskell. It was introduced in Q 7.1. You can find a discussion of this feature in the mailing list archive: http://sourceforge.net/mailarchive/forum.php?thread_name=4463BF32.2020900%40t-online.de&forum_name=q-lang-users It makes it much easier to define non-special functions by pattern matching on lazy data structures. Special functions work as before (they will not do any automatic evaluations when matching special subterms), so declaring g to be a special form as well will give you the behaviour that you want. Cheers, Albert Marco Maggesi wrote: > Unfortunately, I found another obstacle (bug?). > I really do not understand this: given the program > > special expr E; > f (expr X) = expr X; > g (expr 0) = expr 0; > g (expr X) = expr X; > > I get > > ==> f (expr random) > expr random > > ==> g (expr random) > expr 2635609360 -- 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 |
From: Alexander N. <AN...@sp...> - 2007-05-17 17:00:24
|
Hello Tim, Thursday, May 17, 2007, 12:19:18 PM, you wrote: TH> Might () be appropriate? Great idea. While [] could be a 'proper' answer sometimes, empty tuple is never a value. TH> As a bonus idea, can you seek to work with lists more, thereby allowing a TH> filter (<>()) expression as a tidy-up phase (before or after getmax-ing)? In fact, I already changed the dist. Now it returns list of distances, the whole path from A to B and [] is a valid failure designator - it means 'no path found' AG> but IMHO it just doesn't AG> seem to fit the rewriting model very well, where each equation is AG> considered a separate entity. Well, for me it's just a shortcut and it is always clear where it belongs to. The only problem is existing code which may use global variables with the same name. AG> I was talking about an operation which AG> bails out of the current reduction, not a general-purpose sentinel value AG> to be returned by a function. AG> Alexander, I think that this is what you wanted, right? Well, maybe. Here's how I see it : length [] = 0; length [H|T] = _FAIL_ if (islist H); = 1+length T otherwise; but also look at : len [] = 0; len [[H|Hs]|T] = _FAIL_; len [H|T] = 1+len T; so semantics of _FAIL_ would be : rewrite the current match with itself and return. So, 'fail' applies to the left side, but _FAIL_ applies to the right side. no matter how you call it - reject, normal, agree, refuse - which strangely means the same. Each time I am learning a new language I am thinking about how I would implement it. It helps understanding and in fact it is the only time when I can think about it. When I am already used to a language I just use it. For example (X+Y)*Z = X*Z+Y*Z; X*(Y+Z) = X*Y+X*Z; is good, but X+Y = Y+X; // commutative rule will not work. -- Best regards, Alexander mailto:AN...@sp... |
From: John C. <co...@cc...> - 2007-05-17 16:11:32
|
Albert Graef scripsit: > The specific application was shortest path computations, where it makes > perfect sense to use 'inf' for the length of a non-existing edge, Ah, of course. Post in haste, repent at leisure, that's me. -- And it was said that ever after, if any John Cowan man looked in that Stone, unless he had a co...@cc... great strength of will to turn it to other http://ccil.org/~cowan purpose, he saw only two aged hands withering in flame. --"The Pyre of Denethor" |
From: Albert G. <Dr....@t-...> - 2007-05-17 16:01:18
|
John Cowan wrote: > Presumably "const bottom;" somewhere in the standard library is enough? > I like the name "bottom". No, that's a misunderstanding. I was talking about an operation which bails out of the current reduction, not a general-purpose sentinel value to be returned by a function. That is, an operation like 'fail' [http://q-lang.sourceforge.net/qdoc/qdoc_10.html#IDX287], but making the entire reduction fail (effectively turning the redex being reduced into a normal form), not just the current equation. Example: foo X Y = _FAIL_ if not (isnum X and then isnum Y); = /* ... */; So, e.g., 'foo 99 bla' would be a normal form, but subsequent equations may be tried if X and Y are both numbers. Alexander, I think that this is what you wanted, right? > IMHO it's better to use "nan" than "inf" in the numeric case. It has > exactly the right semantics. The specific application was shortest path computations, where it makes perfect sense to use 'inf' for the length of a non-existing edge, because X+inf = inf and max X inf = inf if X is either a number or inf. That's also what you'll see in many text book algorithms for the shortest path problem, whether it is Bellman-Ford, Dijkstra, or the maxtrix-based algorithms. Of course this only works for algorithms where you don't have to distinguish between non-existing and infinite-length edges. 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 |
From: John C. <co...@cc...> - 2007-05-17 14:08:09
|
Albert Graef scripsit: > As you point out, it would be nice to have a 'fail' which not only fails > the current equation, but *all* equations for the current redex. That's > an interesting idea, because it doesn't interfere as much with the > rewriting semantics as the catch/throw exception handling which Q > already offers as a means to exit a function anywhere. Shame on me that > I didn't think about this before! ;-) I'm tempted to actually implement > this as an experimental feature. What does everybody else think about > this? How should we name this operation? Presumably "const bottom;" somewhere in the standard library is enough? I like the name "bottom". > In this special case it would make sense to use 'inf' (defined in > math.q) as a sentinel value for non-existing links. IMHO it's better to use "nan" than "inf" in the numeric case. It has exactly the right semantics. -- Work hard, John Cowan play hard, co...@cc... die young, http://www.ccil.org/~cowan rot quickly. |
From: Albert G. <Dr....@t-...> - 2007-05-17 12:08:40
|
Hi Alexander, well, it seems that John and Tim already answered most of your questions, but anyway, here are my $0.02. Of course you know that your problem isn't in any way Q-specific. If it wasn't for those pesky error conditions, all of our programs would be much easier to write and look much cleaner. ;-) As you point out, it would be nice to have a 'fail' which not only fails the current equation, but *all* equations for the current redex. That's an interesting idea, because it doesn't interfere as much with the rewriting semantics as the catch/throw exception handling which Q already offers as a means to exit a function anywhere. Shame on me that I didn't think about this before! ;-) I'm tempted to actually implement this as an experimental feature. What does everybody else think about this? How should we name this operation? Alexander Nickolsky wrote: > Suppose I have a function that may return a value, but also may > fail. For example, length of a path in a graph. If nodes are > interconnected, there is length, if no - there is no length. > Returning some 'special' value like 0 or 99999 is generally a > bad practice. In this special case it would make sense to use 'inf' (defined in math.q) as a sentinel value for non-existing links. Maybe you want to look at my dijkstra.q example: http://q-lang.sourceforge.net/examples/dijkstra.q (I don't claim that this example is particularly elegant, but at least it's purely functional. Also note that the example still uses its own definition of 'inf', as it was written for an older version of the standard library; you don't need that any more.) > Another example is further processing of results. Say, I want > to find the longest path. It leads to the expression : > > if ((isnum P) and (isnum Q)) then (max P Q) else if (isnum P) then P > else if (isnum Q) then Q where P = (dist (A,B) N ), Q = (dist (C,D) N ); As Tim already pointed out, in Q you usually have lot of little helper functions in your programs. How about this: getmax (A,B) (C,D) = maxdist P Q where P = dist (A,B) N, Q = dist (C,D) N; maxdist X:Num Y:Num = max X Y; maxdist X:Num _ = X; maxdist _ Y:Num = Y; // if you want/need a special sentinel value: //maxdist _ _ = bad_value otherwise; Or, if you'd rather want 'getmax' itself to fail: getmax (A,B) (C,D) = M where P = dist (A,B) N, Q = dist (C,D) N, M:Num = maxdist P Q; Readable enough? > Also it is sometimes not handy that 'where' clause belongs to one > equation only. If it was not so, I could write > > getmax (A,B) (C,D) = (max P Q) if (isnum P) and (isnum Q); > = P if (isnum P); > = Q if (isnum Q); where P = (dist (A,B) N ), Q = > (dist (C,D) N ); > > which is much more readable. Yes, that's the way it is done in Miranda -- 'where' clauses are attached to "definitions" which may consist of any number of guarded equations for the same left-hand side. I agree that this is useful, but it is also a fairly rigid scheme. In contrast, Q allows you to mix guards and 'where' clauses freely, which isn't possible in Miranda. I considered this more useful when designing the Q equation syntax. From the technical POV, it wouldn't be impossible to have local definitions and guards spanning multiple equations sharing the same lhs (in fact we discussed this before; we'd have to design a suitable syntax, and the VM would have to be modified to support this), but IMHO it just doesn't seem to fit the rewriting model very well, where each equation is considered a separate entity. Anyway, as the example above shows you can work around this limitation with helper functions. Or you could use 'cond' instead: getmax (A,B) (C,D) = cond (isnum P and then isnum Q, max P Q; isnum P, P; isnum Q, Q; true, bad_value) where P = dist (A,B) N, Q = dist (C,D) N; Looks a bit too Lispy for my taste. ;-) But YMMV. Cheers, 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 |
From: Marco M. <ma...@ma...> - 2007-05-17 10:23:06
|
On May 16, 2007, at 2:25 AM, Albert Graef wrote: > ma...@ma... wrote: >> I just got burned by this unexpected (for me, of course) behavior of >> list comprehension. Given the program >> >> delta X X = 1; >> delta _ _ = 0 otherwise; >> tabulate N M F = [[F I J : I in [1..N]] : J in [1..M]]; >> eye N = tabulate N N delta; >> >> then (eye 2) evaluates to [[0,0],[0,0]] instead of [[1,0],[0,1]] as I >> would have imagined. > > Ok, this bug is fixed in cvs now (qmfuns.c revision 1.62). > > ==> eye 2 > [[1,0],[0,1]] Thanks. Unfortunately, I found another obstacle (bug?). I really do not understand this: given the program special expr E; f (expr X) = expr X; g (expr 0) = expr 0; g (expr X) = expr X; I get ==> f (expr random) expr random ==> g (expr random) expr 2635609360 M. |
From: Tim H. <q...@st...> - 2007-05-17 08:19:44
|
Alexander Nickolsky <AN...@sp...> writes: [snip] > Then there comes another problem. Suppose I have a list of values > that I want to process using function like this, leaving only > results that make sense, that are 'proper' values. > It seems to me that I cannot make this procedure polymorphic, > because if for example 'false' means unwanted value for integer > function, 0 could mean unwanted value for boolean function, etc. > Another example is further processing of results. Say, I want > to find the longest path. It leads to the expression : > > if ((isnum P) and (isnum Q)) then (max P Q) else if (isnum P) then P > else if (isnum Q) then Q where P = (dist (A,B) N ), Q = (dist (C,D) N ); > > I do not think it's very readable. Wouldn't it be nice to have a > common 'special' value like nil or NULL or whatever, to indicate > failure ? Might () be appropriate? Without going too far into the specifics of your algorithm, the two things I would be doing are a) giving your expression a name - specifically, use more helper functions. You could invent "getmaxh" which takes all the (A,B) and (C,D) and dist (A,B) N and all that, which pushes the conditional checks down a level b) seek to use guards: write more rules for getmaxh that have the "when" on the left side: getmaxh (A,B) (C,D) () = (); getmaxh (A,B) (C,D) Z:Integer = foo; getmaxh (A,B) (C,D) Z = bar; //general case getmax (A,B) (C,D) = something to do with getmaxh introducing the Z parameter; As a bonus idea, can you seek to work with lists more, thereby allowing a filter (<>()) expression as a tidy-up phase (before or after getmax-ing)? ~Tim -- <http://spodzone.org.uk/> |
From: John C. <co...@cc...> - 2007-05-17 02:21:00
|
Albert Graef scripsit: > Hmm, do you mean that something like \X.(\X.X) X should be an error? Yes. > I don't think that this is a very good idea because it renders alpha > conversion, as it is usually defined, invalid. Not so much invalid as pointless. > You might argue that this is just a theoretical issue and we should > give in to the practical demands of programmers here. But if you > write a program that takes apart and manipulates lambda expressions > (as you can do in Q), it's quite tedious if you can't just rename > bound variables without keeping track of the entire context. True enough; rebinding is useful for program generators. I think it's a bad idea for human programmers, though. > But IMHO it's much less of a problem in Q (unless you try really hard > to program in an Algol'ish style in Q), since Q pretty much forces > you to write lots of little equations without nested scopes. I agree. -- What is the sound of Perl? Is it not the John Cowan sound of a [Ww]all that people have stopped co...@cc... banging their head against? --Larry http://www.ccil.org/~cowan |
From: Albert G. <Dr....@t-...> - 2007-05-17 02:01:47
|
John Cowan wrote: > IMNSHO, rebinding of lexical variables in an inner scope is a bug in > Algol 60 that has leaked into most other programming languages. > It is almost always the result of a programmer error, and instead > of quietly repairing the code with alpha conversion, compilers should > at least warn, and ideally go BZZZT WRONG when they see such a rebinding. Hmm, do you mean that something like \X.(\X.X) X should be an error? I don't think that this is a very good idea because it renders alpha conversion, as it is usually defined, invalid. You might argue that this is just a theoretical issue and we should give in to the practical demands of programmers here. But if you write a program that takes apart and manipulates lambda expressions (as you can do in Q), it's quite tedious if you can't just rename bound variables without keeping track of the entire context. I haven't read the original (1932?) paper on the lambda calculus by Church, but I'm pretty sure that the possibility to rebind variables in inner scopes was in the calculus from the very beginning, predating Algol by some 25 years, so it's certainly not a bug that has "leaked from Algol 60". Rather, I think that Algol picked up some ideas from the lambda calculus there. But I'm not a lambda calculus expert, for me it's just a convenience to quickly write down a "throwaway" function. Maybe someone more versed in the history of the lambda calculus can shed some light on this? Anyway, I agree that shadowed parameters and locals are a big problem in Algol-like languages, but IMHO that's mainly due to a programming style which favours deep nesting of scopes with big chunks of code inside. Alas, lots of Lisp code also looks like this, and to some extent this also applies to Haskell and ML with their nested scoping. But IMHO it's much less of a problem in Q (unless you try really hard to program in an Algol'ish style in Q), since Q pretty much forces you to write lots of little equations without nested scopes. That style also has its problems, of course -- sometimes it's hard not to miss the wood for the trees. ;-) Cheers, 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 |
From: John C. <co...@cc...> - 2007-05-16 22:03:15
|
Alexander Nickolsky scripsit: > I do not think it's very readable. Wouldn't it be nice to have a > common 'special' value like nil or NULL or whatever, to indicate > failure ? Any value for which there are no reduction rules will serve the purpose, since failure in Q just means being in normal form already. So just write "const NULL;" at the top of your code, and all will be well. -- You're a brave man! Go and break through the John Cowan lines, and remember while you're out there co...@cc... risking life and limb through shot and shell, http://ccil.org/~cowan we'll be in here thinking what a sucker you are! --Rufus T. Firefly |
From: Alexander N. <AN...@sp...> - 2007-05-16 18:36:55
|
Hello q-lang-users, I'm constantly running into some problem in Q that I'll try to describe. Probably it's because of my Prolog background. Suppose I have a function that may return a value, but also may fail. For example, length of a path in a graph. If nodes are interconnected, there is length, if no - there is no length. Returning some 'special' value like 0 or 99999 is generally a bad practice. Due to polymorphic nature of Q I can return a value of another type, like false or []. Note that 'fail'-ing sometimes requires additional level of function nesting, because it applies to one equation only but not to function itself. Then there comes another problem. Suppose I have a list of values that I want to process using function like this, leaving only results that make sense, that are 'proper' values. It seems to me that I cannot make this procedure polymorphic, because if for example 'false' means unwanted value for integer function, 0 could mean unwanted value for boolean function, etc. Another example is further processing of results. Say, I want to find the longest path. It leads to the expression : if ((isnum P) and (isnum Q)) then (max P Q) else if (isnum P) then P else if (isnum Q) then Q where P = (dist (A,B) N ), Q = (dist (C,D) N ); I do not think it's very readable. Wouldn't it be nice to have a common 'special' value like nil or NULL or whatever, to indicate failure ? Also it is sometimes not handy that 'where' clause belongs to one equation only. If it was not so, I could write getmax (A,B) (C,D) = (max P Q) if (isnum P) and (isnum Q); = P if (isnum P); = Q if (isnum Q); where P = (dist (A,B) N ), Q = (dist (C,D) N ); which is much more readable. Just thoughts. Maybe I am looking from the wrong side. In Prolog I can just fail a predicate. -- Best regards, Alexander mailto:AN...@sp... |
From: John C. <co...@cc...> - 2007-05-16 14:01:51
|
Albert Graef scripsit: > But note what happens, e.g., if a nested 'let' attempts to bind a > variable which is already bound by an outer 'let' expression: <rant> IMNSHO, rebinding of lexical variables in an inner scope is a bug in Algol 60 that has leaked into most other programming languages. It is almost always the result of a programmer error, and instead of quietly repairing the code with alpha conversion, compilers should at least warn, and ideally go BZZZT WRONG when they see such a rebinding. </rant> -- You know, you haven't stopped talking John Cowan since I came here. You must have been http://www.ccil.org/~cowan vaccinated with a phonograph needle. co...@cc... --Rufus T. Firefly |