Next: , Up: Pre-Scheme


9.1 Differences between Pre-Scheme & Scheme

Pre-Scheme is often considered either a dialect of Scheme or a subset of Scheme. However, there are several very important fundamental differences between the semantics of Pre-Scheme & Scheme to detail.

There is no garbage collector in Pre-Scheme.
All memory management is manual, as in C, although there are two levels to memory management, for higher- and lower-level purposes: pointers & addresses. Pointers represent higher-level data that are statically checked for type coherency, such as vectors of a certain element type, or strings. Addresses represent direct, low-level memory indices.


Pre-Scheme has no closures.
Lambda expressions that would require full closures at run-time — e.g., those whose values are stored in the heap — are not permitted in Pre-Scheme. However, the Pre-Scheme compiler can hoist many lambda expressions to the top level, removing the need of closures for them. (Closures would be much less useful in the absence of garbage collection, in any case.) If the Pre-Scheme compiler is unable to move a lambda to a place where it requires no closure, it signals an error to the user.


Tail call optimization is not universal.
The Pre-Scheme compiler optimizes tail calls where it is possible — typically, just in local loops and top-level procedures that are not exported from the package, but there are other heuristics —, but it is not universal. Programmers may force tail call optimization with Pre-Scheme's goto special form (see Tail call optimization in Pre-Scheme), but, in situations where the compiler would not have optimized the tail call, this can make the generated code have to jump through many hoops to be a tail call — often necessitating code bloat, because the code of the tail-called procedure is integrated into the caller's driver loop —; and, where the compiler would have otherwise optimized the tail call, goto has no effect anyway.


Types are strictly verified with Hindley-Milner type inference.
The types of Pre-Scheme programs are statically verified based on Hindley-Milner type inference, with some modifications specific to Pre-Scheme. Type information is not retained at run-time; any tagging must be performed explicitly.


Pre-Scheme does not support first-class continuations.
There is no call-with-current-continuation or other continuation manipulation interface. It has been suggested that downward-only continuations, based on C's setjmp & longjmp, might be implemented in the future, but this is not yet the case.1


The full numeric tower of R5RS is not supported by Pre-Scheme.
Pre-Scheme's only numeric types are fixnums and flonums, with precision determined by the architecture on which the Pre-Scheme code runs. Fixnums are translated to C as the long type; flonums are translated as the float type.


Top-level Pre-Scheme code is evaluated at compile-time.
Closures actually are available, as long as they may be eliminated before run-time. Code evaluated at compile-time also does not require satisfaction of strict static typing. Moreover, certain procedures, such as vector-length, are available only at compile-time.

Footnotes

[1] It may be possible to use Pre-Scheme's C FFI to manually use setjmp & longjmp, but the author of this manual cannot attest to this working.