Re: [q-lang-users] Special values or failing functions
Brought to you by:
agraef
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 |