Here's a note from Kent Dybwig in response:
This is an interesting question.
When launched with a - script that uses REPL semantics, the variables defined in the script, such as list-enumerate and list-index, are mutable, which inhibits cross-procedure optimization, including embedding. when run with -program, however the variables are immutable, which allows interprocedural optimizations.
In this case, --program allows the compiler to include in the list-enumerate list in the list-index body and, in turn, the lambda expression in the list-index index, the body to list — to list the body. The end result is a conditional expression in the expression of the manufacturer. This causes the compiler to create a closure for the consumer to avoid code duplication along conditional branches and so on. This closure is created each time through a list-enumerate cycle, resulting in additional distribution overhead. How often optimization happens. Mostly you win, but sometimes you lose. The good news is, in general, the benefits of the weight it costs, even in your program. I called list-index in a loop (modified code below) and found that with --program, the code runs about 30% faster.
Kent
(import (chezscheme))
(define (list-enumerate ls val proc)
(let loop ((ls ls) (return? #f) (val val))
(if (or (null? ls)
return?)
val
(call-with-values (lambda () (proc val (car ls)))
(lambda (return? val)
(loop (cdr ls) return? val))))))
(define (list-index ls proc)
(list-enumerate ls
0
(lambda (i elt)
(if (proc elt)
(values #ti)
(values #f (+ i 1))))))
(define n 100000)
(define data (time (iota n)))
(let ()
(define runalot
(lambda (i thunk)
(let loop ([ii])
(let ([x (thunk)])
(if (fx = i 1)
x
(loop (fx- i 1)))))))
(time
(runalot 1000
(lambda ()
(list-index data (lambda (elt) (= elt (- n 1))))))))
source share