Scheme expressions combine the features of expressions and statements. They return values, but they can also have side effects---i.e., they can change the state of variables or objects by assignment.
The variable assignment operation in Scheme is set!
, pronounced
"set-bang." If we want to assign the value 3 to the variable foo
,
we write
(set! foo 3)
which is pretty much equivalent to C's
foo = 3;
Note that (set! foo 3)
looks like a function call, because
everything uses prefix notation, but it's not really a call; it's
a different kind of expression.
You should not use assignments a lot in Scheme programs. It's usually a sign of bad style, as I'll explain later. I'll also show how to program in a style that doesn't need side effects much. They're there if you need them, though.
When you write a procedure that modifies its arguments, rather than just just returning a value, it's good style to give it a name that ends with an exclamation mark. This reminds you and anybody reading your code that the procedure changes something that already exists, rather than just returning a value such as a new data structure. Most of the standard Scheme procedures that change state are named this way.
Most Scheme procedures don't modify anything, however. For example,
the standard procedure reverse
takes a list as its argument and
returns a list of the same elements in the opposite order. That is
it returns a kind of reversed copy of the original list, without
modifying the original at all. If you wrote a procedure that returned
the same list, but modified so that its elements were in the
opposite order, you'd probably call it reverse!
. This warns
people that a list that is passed to reverse!
may be changed.
One side-effecting procedure we'll use in examples is display
.
display
takes a value and writes a printed representation to
the screen or a file. If you give it one argument, it writes to the
"standard output"; by default, that's the terminal or other display.
For example, if you want to show the user the printed representation of the number 1022, you can use the expression
(display 1022)
The side effect of executing this expression is to write the 1022
on
the user's screen. (display
automatically converts the number
to a string of characters so that you can read it.)
Note that display
doesn't have an exclamation point at the end
of its name, because it doesn't side-effect the argument you give it
to print. You can give it a data structure and be sure that it won't
modify it; display does have a side-effect, though--it changes
the state of the screen (or file) that it writes to.
display
is fairly flexible, and can write the printed representations
of many common Scheme objects, and even fairly complex data structures.
Among many other things, display can print character strings. (Strings
are another kind of Scheme object. You can write a literal string in
double quotes, "like this"
, and Scheme constructs a string object
to hold that character sequence.
The expression (display "Hello, world!)
has the side effect
of writing Hello, world!
to the standard output, which is usually
the user's screen.
This makes display
very useful for debugging, and for little examples,
as well as for writing interactive programs. A similar procedure, write
is used for saving data structures to files; they can then be copied back
into memory using read
.
In a later chapter, I'll show how to write to files by passing a second
argument to display
that tells it where to send the output. For now,
you should just use display
with exactly one argument.
Don't try to pass display
several things and expect it to
print them all.