Go to the first, previous, next, last section, table of contents.

Expressions Return Values, But May Have Side-Effects

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.

Go to the first, previous, next, last section, table of contents.