> Can't you just add a unique tag to procedures derived, one
> way or another, from the same invocation of lambda and then
> compare procedures by comparing their tags? Sure, it slows
> down eqv?, but probably that's a price worth paying to speed
> up procedure calls.

You could do that, but it would be both slower and more
complicated than the usual implementation in which a closure's
address serves as its tag.

What you're missing is that optimizing compilers don't allocate
closures for procedures that are used only in operator position.

Here's an artificial but pedagogical example:

(define (f m n)
  (define (g i)
    (define (h j)
      (if (= j 0)
          #t
          (g (- j 1))))
    (if (= i 0)
        (if (= i m)
            (list h)    ; closure must be allocated here
            #f)
        (h (- i 1))))
  (g n))

With the R6RS semantics, a compiler is allowed to rewrite the
(list h) as (list (lambda (j) (h j))), which means the closure
will be allocated only if i=m=0.  With that rewrite, f allocates
no storage at all unless its first argument is zero.

On my laptop, running Larceny, that makes f run twice as fast.
In systems with equally good compilers but less performant garbage
collectors, the performance advantage of the R6RS semantics on
this example would be even greater.

On more typical examples of tight loops in which the loop procedure
escapes under some exceptional circumstances, the slowdown may be
50% instead of 100%.  That's the price you pay for using the R5RS
semantics instead of the R6RS semantics.

Will

_______________________________________________
r6rs-discuss mailing list
r6rs-discuss@lists.r6rs.org
http://lists.r6rs.org/cgi-bin/mailman/listinfo/r6rs-discuss

Reply via email to