A long time ago, on 9 May, Alan Watson wrote: > Thanks very much for that explanation. I've got two further comments. > > First, a sufficiently clever compiler could arrange that (lambda (j) (h j)) > have the same tag as h and thereby, with an eqv? that checks tags rather > than just addresses, preserve R5RS eqv?.
Maybe I'm not sufficiently clever, but I don't see how that could work. If h is the name of a known local procedure that's referenced only in call position, then the compiler shouldn't have to allocate a closure *or* a tag for it. (Allocating unique tags is almost as expensive as allocating a closure.) > Second, the R6RS semantics would be more convincing if they were > justified on the basis of real code rather than artificial examples. > I understand that's difficult. I also understand that you're never > going to convince everyone; I have long given up worrying about > factors of two. When I was working with the R6RS editors, we scoured several code bases looking for real examples that relied upon the R5RS semantics. We found very few examples. If I recall correctly, the majority of the examples we did find were incorrect or at least non-portable. Almost all of the correct examples we found were efficiency hacks that were intended to speed up some common special case; since the general-case code would suffice, these efficiency hacks would be of no interest to people who don't worry about factors of two. Consider, for example, the reference implementation for SRFI 69 (Basic hash tables). Its implementation of make-hash-table calls appropriate-hash-function-for, which uses eq? (not eqv?) tests on comparison procedures to try to identify an appropriate hash function. That attempt succeeds only if the comparison procedure is eq?, string=?, or string-ci=?. Otherwise it defaults to a general purpose hash function that would work just as well with the three special cases (*). Hence the only purpose of those tests is to improve performance. (*) Well, almost as well. The general purpose hash function refuses to hash procedures. That's just a deliberate bug in the reference implementation of the default hash function. On the other hand, the R5RS semantics for eqv? on procedures appears to have encouraged the designer of SRFI 69 to make a serious mistake in his design. If you provide a comparison procedure but no matching hash function, the implementation is supposed to infer an appropriate hash function. Although that works for a few simple comparison procedures such as eq? and equal?, it can't work in general: There is absolutely no way to infer an appropriate hash function for comparison procedures such as (lambda (x y) ;; the cdrs of x and y consist entirely of irrelevant comments, ;; which we should ignore when testing for equality (= (car x) (car y)) Bottom line: 1. The R5RS semantics for eqv? on procedures is hard to use correctly. Most of the uses we found were incorrect or at least non-portable. 2. Most of the correct uses that we found were mere efficiency hacks. Since the efficiency that's lost by supporting the R5RS semantics is considerably more important than the efficiency that's gained, the efficiency argument goes against the R5RS semantics. 3. The R5RS semantics appears to encourage the design of fragile APIs that may work for some common cases but don't work in general. Will _______________________________________________ r6rs-discuss mailing list r6rs-discuss@lists.r6rs.org http://lists.r6rs.org/cgi-bin/mailman/listinfo/r6rs-discuss