Aziz,
(and any other compiler wizards in the audience)
Here's 'list-recursion' from yesterday:
(define (list-recursion f g h)
(define (rec fun lst)
(let loop ((lst lst))
(if (null? lst)
(f lst)
(let ((hd (car lst))
(tl (cdr lst)))
(let ((val (fun hd)))
(if val
(g loop val hd tl)
(h loop val hd tl)))))))
rec)
Here's a version of 'count' with an implementation based on the above:
(define (zero x) 0)
(define add-1-recur
(lambda (loop vl hd tl)
(+ 1 (loop tl))))
(define recur
(lambda (loop vl hd tl)
(loop tl)))
(define (count fun lst)
(let loop ((lst lst))
(if (null? lst)
(zero lst)
(let ((hd (car lst))
(tl (cdr lst)))
(let ((val (fun hd)))
(if val
(add-1-recur loop val hd tl)
(recur loop val hd tl)))))))
With this version, there's a one-time up-front cost of 8 bytes:
(time (count odd? '()))
> running stats for (count odd? '()):
no collections
0 ms elapsed cpu time, including 0 ms collecting
0 ms elapsed real time, including 0 ms collecting
8 bytes allocated
Demonstrating that it stays at 8 bytes:
> (time (count odd? '(1 2 3 4 5 6)))
running stats for (count odd? '(1 2 3 4 5 6)):
no collections
0 ms elapsed cpu time, including 0 ms collecting
0 ms elapsed real time, including 0 ms collecting
8 bytes allocated
3
>
Now, consider the same definition of count, with the 'add-1-recur' and
'recur' control flow combinators inlined:
(define (zero x) 0)
(define (count fun lst)
(let loop ((lst lst))
(if (null? lst)
(zero lst)
(let ((hd (car lst))
(tl (cdr lst)))
(let ((val (fun hd)))
(if val
(+ 1 (loop tl))
(loop tl)))))))
Zero allocation:
> (time (count odd? '()))
running stats for (count odd? '()):
no collections
0 ms elapsed cpu time, including 0 ms collecting
0 ms elapsed real time, including 0 ms collecting
0 bytes allocated
0
> (time (count odd? '(1 2 3 4 5 6)))
running stats for (count odd? '(1 2 3 4 5 6)):
no collections
0 ms elapsed cpu time, including 0 ms collecting
0 ms elapsed real time, including 0 ms collecting
0 bytes allocated
In principle, can a compiler be smart enough to perform the inlines so
as to achive the zero-allocation behaviour? Or is there something about
the design of the combinator itself which prevents this?
Ed