In plain R5RS Scheme, there is no module system -- only the toplevel. Furthermore, the mentality is that everything can be modified, so you can "customize" the language any way you want. But without a module system this does not work well. For example, I write
(define (sub1 x) (- x 1))
in a library which you load -- and now you can redefine -
:
(define - +) ; either this
(set! - +) ; or this
and now you unintentionally broke my library which relied on sub1
decrementing its input by one, and as a result your windows go up when you drag them down, or whatever.
The only way around this, which is used by several libraries, is to "grab" the relevant definition of the subtraction function, before someone can modify it:
(define sub1 (let ((- -)) (lambda (x) (- x 1))))
Now things will work "more fine", since you cannot modify the meaning of my sub1
function by changing -
. (Except... if you modify it before you load my library...)
Anyway, as a result of this (and if you know that the -
is the original one when the library is loaded), some compilers will detect this and see that the -
call is always going to be the actual subtraction function, and therefore they will inline calls to it (and inlining a call to -
can eventually result in assembly code for subtracting two numbers, so this is a big speed boost). But like I said in the above comment, this is more coincidental to the actual reason above.
Finally, R6RS (and several scheme implementations before that) has fixed this and added a library system, so there's no use for this trick: the sub1
code is safe as long as other code in its library is not redefining -
in some way, and the compiler can safely optimize code based on this. No need for clever tricks.