Function applications are delayed, and promises are automatically
forced. The language provides bindings that are equivalent to most of
the racket/base and racket/list
libraries. Primitives are strict in the expected places; struct
constructors are lazy; if, and, or etc.
are plain (lazy) functions. Strict functionality is provided as-is:
begin, I/O, mutation, parameterization, etc. To have your
code make sense, you should chain side effects in begins,
which will sequence things properly. (Note: This is similar to
threading monads through your code—only use begin where
order matters.)

Mixing lazy and strict code is simple: you just write the lazy code in
the lazy language, and strict code as usual. The lazy language treats
imported functions (those that were not defined in the lazy language)
as strict, and on the strict side you only need to force (possibly
recursively) through promises.

A few side-effect bindings are provided as-is. For example,
read and printf do the obvious thing—but note that
the language is a call-by-need, and you need to be aware when promises
are forced. There are also bindings for begin (delays a
computation that forces all sub-expressions), when,
unless, etc. There are, however, less reliable and might
change (or be dropped) in the future.

There are a few additional bindings, the important ones are special
forms that force strict behaviour—there are several of these that
are useful in forcing different parts of a value in different ways, as
described in Forcing Values.