• Aucun résultat trouvé

Input and Output

Dans le document ANSI Common Lisp (Page 35-39)

Welcome to Lisp

SUM-GREATER

2.9 Input and Output

So far we have done I/O implicitly, by taking advantage of the toplevel. For real interactive programs this is not likely to be enough. In this section we look at a few functions for input and output.

The most general output function in Common Lisp is f ormat. It takes two or more arguments: the first indicates where the output is to be printed, the second is a string template, and the remaining arguments are usually objects whose printed representations are to be inserted into the template. Here is a typical example:

> (format t "~A plus ~A equals ~ A . T ' 2 3 ( + 2 3)) 2 plus 3 equals 5.

NIL

Notice that two things get displayed here. The first line is displayed by f ormat. The second line is the value returned by the call to f ormat, displayed in the usual way by the toplevel. Ordinarily a function like format is not called directly from the toplevel, but used within programs, so the return value is never seen.

The first argument to format, t, indicates that the output is to be sent to the default place. Ordinarily this will be the toplevel. The second argument is a string that serves as a template for output. Within this string, each ~A indicates a position to be filled, and the ~% indicates a newline. The positions are filled by the values of the remaining arguments, in order.

The standard function for input is read. When given no arguments, it reads from the default place, which will usually be the toplevel. Here is a function that prompts the user for input, and returns whatever is entered:

2.10 VARIABLES 19 (defun askem ( s t r i n g )

(format t ""A" s t r i n g ) ( r e a d ) )

It behaves as follows:

> (askem "How old are you? ") How old are you? 29

29

Bear in mind that read will sit waiting indefinitely until you type some-thing and (usually) hit return. So it's unwise to call r e a d without printing an explicit prompt, or your program may give the impression that it is stuck, while in fact it's just waiting for input.

The second thing to know about read is that it is very powerful: r e a d is a complete Lisp parser. It doesn't just read characters and return them as a string. It parses what it reads, and returns the Lisp object that results. In the case above, it returned a number.

Short as it is, the definition of askem shows something we haven't seen before in a function. Its body contains more than one expression. The body of a function can have any number of expressions. When the function is called, they will be evaluated in order, and the function will return the value of the last one.

In all the sections before this, we kept to what is called "pure" Lisp—that is, Lisp without side-effects. A side-effect is some change to the state of the world that happens as a consequence of evaluating an expression. When we evaluate a pure Lisp expression like (+ 1 2), there are no side-effects; it just returns a value. But when we call format, as well as returning a value, it prints something. That's one kind of side-effect.

When we are writing code without side-effects, there is no point in defin-ing functions with bodies of more than one expression. The value of the last expression is returned as the value of the function, but the values of any preceding expressions are thrown away. If such expressions didn't have side-effects, you would have no way of telling whether Lisp bothered to evaluate them at all.

2.10 Variables

One of the most frequently used operators in Common Lisp is l e t , which allows you to introduce new local variables:

> ( l e t ((x 1) (y 2)) (+ x y ) )

3

A l e t expression has two parts. First comes a list of instructions for creating variables, each of the form (variable expression). Each variable will ini-tially be set to the value of the corresponding expression. So in the example above, we create two new variables, x and y, which are initially set to 1 and 2, respectively. These variables are valid within the body of the l e t .

After the list of variables and values comes a body of expressions, which are evaluated in order. In this case there is only one, a call to +. The value of the last expression is returned as the value of the l e t . Here is an example of a more selective version of askem written using l e t :

(defun ask-number ()

(format t "Please enter a number. ") (let ((val (read)))

(if (numberp val) val

(ask-number))))

This function creates a variable v a l to hold the object returned by read.

Because it has a handle on this object, the function can look at what you entered before deciding whether or not to return it. As you probably guessed, numberp is a predicate that tests whether its argument is a number.

If the value entered by the user isn't a number, ask-number calls itself.

The result is a function that insists on getting a number:

> (ask-number)

Please enter a number, a

Please enter a number, (ho hum) Please enter a number. 52 52

Variables like those we have seen so far are called local variables. They are only valid within a certain context. There is another kind of variable, called a global variable, that can be visible everywhere.2

You can create a global variable by giving a symbol and a value to defparameter:

> (defparameter *glob* 99)

•GLOB*

Such a variable will then be accessible everywhere, except in expressions that create a new local variable with the same name. To avoid the possibility of this happening by accident, it's conventional to give global variables names

2The real distinction here is between lexical and special variables, but we will not need to consider this until Chapter 6.

2.11 ASSIGNMENT 21 that begin and end with asterisks. The name of the variable we just created would be pronounced "star-glob-star".

You can also define global constants, by calling def c o n s t a n t : (defconstant limit (+ *glob* 1))

There is no'need to give constants distinctive names, because it will cause an error if anyone uses the same name for a variable. If you want to check whether some symbol is the name of a global variable or constant, use boundp:

> (boundp '*glob*) T

2.11 Assignment

In Common Lisp the most general assignment operator is s e t f . We can use it to do assignments to either kind of variable:

> ( s e t f *glob* 98) 98

> ( l e t ((n 10)) ( s e t f n 2) n)

2

When the first argument to s e t f is a symbol that is not the name of a local variable, it is taken to be a global variable:

> ( s e t f x ( l i s t ' a ' b >c)) (A B C)

That is, you can create global variables implicitly, just by assigning them val-ues. In source files, at least, it is better style to use explicit def parameters.

You can do more than just assign values to variables. The first argument to s e t f can be an expression as well as a variable name. In such cases, the value of the second argument is inserted in the place referred to by the first:

> ( s e t f (car x) ;n ) N

> x (N B C)

The first argument to s e t f can be almost any expression that refers to a particular place. All such operators are marked as "settable" in Appendix D.

You can give any (even) number of arguments to setf. An expression of the form

( s e t f a b c d e f)

is equivalent to three separate calls to s e t f in sequence:

(setf a b) (setf c d) (setf e f)

Dans le document ANSI Common Lisp (Page 35-39)