Subject: Re: MD5 in LISP and abstraction inversions From: Erik Naggum <erik@naggum.net> Date: Fri, 16 Nov 2001 20:53:45 GMT Newsgroups: comp.lang.lisp Message-ID: <3214932822476660@naggum.net> * Bruce Hoult <bruce@hoult.org> | 1) no one is forcing you to implement = and < for every class. But what does it mean to implement < for a new class, supposing for the sake of argument it was a generic function? This remains unclear to me. (< a b c d) has a well-defined meaning for all real number types. (It is less clear what it means for complex numbers, for instance.) E.g., even though we most probably test only (< a b), (< b c), and (< c d), a true return value implies that (< a c), (< a d), and (< b d) are also true, and we are free to exploit this knowledge. To make sure this holds for a user-defined type, it may be necessary to make those tests explicit, meaning that < becomes as expensive as /=. (Some may not have realized that (/= a b c d) is not simply (not (= a b c d)).) We also know that (< a b) and (not (< b a)) is true for numbers, but because of generic function dispatch, (< a b) and (< b a) may be implemented by different methods, and it may no longer hold. Even if we have an implementation of < that dispatches only on its first argument, this would be true. It would also mean that (and (< a b) (< b c)) may yield a different result than (< a c) if only because of which method is called. The probability of creating a royal mess here is staggeringly high, as any C++ programmer who has tried to overload < will know, but no C++ programmer will ever bother to see if a<c if he has done a<b && b<c. The Common Lisp specification of < means that (< a b c) should check for it. | 2) what if your class is a new representation for numbers? Continued | fractions, say. Surely it is useful to be able to add a method to | the < GF in that case? It may not be. For instance, it may make sense to create a set of functions specialized for comparing the lengths of sequences such that no more cdr operations are needed on lists than absolutely necessary to determine the correct result. (length< a b c) is then different from (and (length< a b) (length< b c)), not in value, of course, but the latter would defeat the whole purpose of this function. A generic function that accepted any number of arguments would have to dispatch on the type of one or two arguments, and it would be most natural to implement it as a progression through the argument list, comparing two values at a time, unless one grasps the need to implement it like /=, but in any case, the convenience value of this general implementation technique would make smarter options much less likely to be implemented, and the likelihood of creating a mess that computes wrong values for the implicit would go way up. I think the notion of adding methods to a generic function for a purely mathematical function like < stems from a lack of reasonable builtin support for the necessary numeric types. I mean, how often _should_ you need to add a new kind of number class to a system? Rather than optimize for this extremely unlikely need, optmizing for the most likely need, i.e., using the existing number classes, seems like good engineering. If you really want to build an experimental system, you can do it with the package system, but you would of course not get the benefit of any type declarations unless you had access to the compiler environment. Franz Inc has done some work in that area. It still appears to be one of the more complex things to experiment with and get reasonable performance out of at the same time. If you have an incomplete number stack to begin with, you would need good support for user-defined number types, and C++ has that, but the other way to optimize this situation is to get it right from the start, and I think Common Lisp did that, both in terms of what it made efficient and what it made possible with the package system. /// -- Norway is now run by a priest from the fundamentalist Christian People's Party, the fifth largest party representing one eighth of the electorate. -- Carrying a Swiss Army pocket knife in Oslo, Norway, is a criminal offense.