
bourbaki% scheme Chez Scheme Version 5.0c Copyright (c) 1994 Cadence Research Systems >Chez Scheme is implemented as an interactive interface to the compiler. It first compiles and executes the Scheme source code or object code contained in the files named on the command line, then issues a prompt for further instructions. At this point, you can press <Control/D> if you wants to exit from the interactive interface and return to the shell. (Careful -- an extra <Control/D> will take you out of the shell too.)
Otherwise, you type in definition or an expression after the prompt. A Scheme program has an extremely simple top-level structure: It is a sequence of zero or more definitions and expressions. So the Scheme compiler can treat what is typed in by the programmer as a legal Scheme program that is simply being submitted one constituent at a time. In particular, the Chez Scheme compiler performs incremental compilation of this program, one constituent at a time.
If you give the Chez Scheme interactive interface a definition, it compiles it, stores the result in an internal data structure called an environment, and generates another prompt. If you give it an expression, it compiles and evaluates the expression and prints out the value, then generates another prompt.
define, and ends with a right parenthesis. Here
are two examples. The first defines a global variable
distance and initializes it to 200. The second defines a
function (in Scheme terminology, a ``procedure'') named cube
that takes any number as argument and returns its cube.
(define distance 200) (define (cube n) (* n n n))A Scheme definition can occupy several lines; pressing the <Enter> key does not terminate the definition. Instead, the interactive interface collects all of the input it sees, parsing as it goes, until it detects the right parenthesis that matches the initial left parenthesis; only then does it start compiling. The interface does not respond in any way until it sees that right parenthesis. (However, a programmer who bogs down in the middle of an attempted definition can press <Control/C>, which causes the interactive interface to discard the part of the definition that it has so far collected and to generate a new prompt.)
> distance 200 >This presupposes, of course, that the variable has already been defined. (Scheme variables are always explicitly initialized at the point of definition, so you don't have to worry about seeing a variable that has been defined but still contains garbage.) If you try to evaluate a variable that has not been defined, you get an error message instead of a value, but the interface generates a new prompt as usual:
> ditsance Error: variable ditsance is not bound. Type (debug) to enter the debugger. >Scheme permits a much larger variety of characters to appear inside identifiers than most programming languages do, because in general it does not permit operators to be placed right next to identifiers, without intervening spaces. In particular, the hyphen is commonly used as a break character; it does not denote subtraction unless it is standing by itself. Thus
i-j and top-of-sequence are simple
variables, not subtraction expressions. Asterisks, exclamation points,
question marks, dollar signs, and colons are among the many other
characters that are legal inside variable names and are frequently so
used.Chez Scheme predefines a few hundred procedures, and if you happen to type in the name of a predefined procedure, Chez Scheme evaluates the procedure name, getting the procedure as a data object, and does its best to print out a representation of that procedure:
> sqrt #<system procedure sqrt> >This is not an error from the language's point of view, but it may not be what the programmer had in mind either.
sqrt to
the argument 1000:
> (sqrt 1000) 31.622776601683793 >Even elementary arithmetic operations are treated syntactically as procedure calls in Scheme, giving arithmetic expressions an appearance that novices often find strange:
> (+ (- 8 3)
(* 7 4))
33
>
As this example shows, procedure calls can be nested. In Scheme, deeply
nested procedure calls are considerably more frequent than in procedural
languages like Pascal and C. This is not a symptom of bad style in Scheme
and should not necessarily be reprehended. Note also that expressions,
like definitions, can occupy more than one line.A common beginner's error is to try to infix arithmetic operators. The result looks different depending on whether the programmer remembers to enclose the expression in parentheses:
> (3 + 8) Error: attempt to apply non-procedure 3. Type (debug) to enter the debugger. >Here the compiler notices the left parenthesis at the beginning of the expression
(3 + 8) and decides, correctly, that it is looking
at a procedure call; it then evaluates the expressions between the
parentheses and finds that the first of the values, which is supposed to be
a procedure, is instead a number. This is an error.
> 3 + 8 3 > #<system procedure +> > 8 >In the absence of parentheses, the compiler regards the numeral
3 as a complete and self-sufficient expression, evaluates it
to get the number 3, prints out that value, and generates a prompt. But,
since it hasn't exhausted the input already typed, it immediately sees the
plus sign, which is also a complete and self-sufficient expression, the
name of the predefined addition procedure. So it evaluates that name,
getting the procedure as value, writes out a representation of the
procedure, and generates another prompt. But there is still more input;
the compiler immediately sees the numeral 8, evaluates it,
prints out the result, and generates yet another prompt.You get both of these effects at once if you forget the procedure-call syntax and write something like
> sqrt (1000) #<system procedure sqrt> > Error: attempt to apply non-procedure 1000. Type (debug) to enter the debugger. >The compiler sees the input as two independent expressions, of which the first,
sqrt, is legal and evaluates to a predefined procedure,
while the second, (1000), is illegal, since it has the form of
a procedure call (to a zero-argument procedure), but has a number rather
than a procedure as the value of its first (and only) enclosed
sub-expression.A list of Scheme's predefined procedures can be found in the section on standard procedures of the Revised(4) report on the algorithmic language Scheme, the de facto standard for the language.
Calls to programmer-defined procedures have the same form as calls to predefined procedures:
> (cube 38) 54872 >
if and three sub-expressions:
(if (= denominator 0)
0
(quotient numerator denominator))
The first of the sub-expressions, the test of the conditional,
determines which of the other two sub-expressions (the consequent
and the alternative) should be evaluated: If the test is true,
the consequent provides the value of the if-expression,
whereas if the test is false, the alternative provides that value.
C programmers will recognize this construction -- it's the Scheme
counterpart of the C expression
(denominator == 0) ? 0 : (numerator / denominator)Other Scheme control expressions have various internal structures, but each one begins with a left parenthesis and a keyword and ends with a right parenthesis. The keywords, which may not be used as variables in Scheme, are
and, begin, case,
cond, do, if, lambda,
let, let*, letrec, or,
quasiquote, quote, and set!.
To create an object file frogs.so from a Scheme source code file
frogs.ss, call the compile-file procedure, giving
it as argument a string containing the name of the program file (without
the filetype suffix):
> (compile-file "frogs") >Compilation affects only the loading time, not the execution time, since Chez Scheme compiles every definition as soon as it sees it anyway.
Workshop front door ... Editing ... Debugging ... Scheme bibliography