Eduardo Cavazos wrote:
Offlist, someone pointed this out:
You can write a compose function that uses recursion to handle arbitrary
arity:
(define (compose . fns)
(let comp ((fns fns))
(cond
((null? fns) 'error)
((null? (cdr fns)) (car fns))
(else
(lambda args
(call-with-values
(lambda ()
(apply
(comp (cdr fns))
args))
(car fns)))))))
Sure, but once you get into
(lambda args ...)
and
(apply ... args)
type expressions, you can say goodbye to performance. Good compilers do
better with explicit parameter lists.
And now I can come back to this and prove it.
The 'uni' procedure used in the fib earlier today does compose of two
unary procedures. Let's see the time if we replace that with the general
compose above:
~ # ikarus -O2 --r6rs-script /scratch/_fib-fp-compose-a.scm
running stats for (fib 34):
106 collections
2368 ms elapsed cpu time, including 96 ms collecting
2384 ms elapsed real time, including 106 ms collecting
442922368 bytes allocated
~ #
So yeah, I'm still interested in "macros based on arity". :-)
Ed
----------------------------------------------------------------------
(import (rnrs)
(ikarus))
(define (compose . fns)
(let comp ((fns fns))
(cond
((null? fns) 'error)
((null? (cdr fns)) (car fns))
(else
(lambda args
(call-with-values
(lambda ()
(apply
(comp (cdr fns))
args))
(car fns)))))))
(define (bi f g c)
(lambda (x)
(c (f x)
(g x))))
(define (sub x)
(lambda (y)
(- y x)))
(define (constant x)
(lambda (y)
x))
(define (ifte f g h)
(lambda (x)
(if (f x)
(g x)
(h x))))
(define (less-than= x)
(lambda (y)
(<= y x)))
(define fib
(ifte (less-than= 1)
(constant 1)
(bi (compose (lambda (x) (fib x)) (sub 1))
(compose (lambda (x) (fib x)) (sub 2)) +)))
(time (fib 34))
----------------------------------------------------------------------