📄 00000004.htm
字号:
><I> (push 4 a) </I><BR>(4) <BR>><I> (push 5 a) </I><BR>(5 4) <BR>><I> (pop a) </I><BR>5 <BR>><I> a </I><BR>(4) <BR>><I> (pop a) </I><BR>4 <BR>><I> (pop a) </I><BR>NIL <BR>><I> a </I><BR>NIL <BR> <BR> <BR> <BR>Functions <BR> <BR>You saw one example of a function above. Here are some more: <BR> <BR>><I> (+ 3 4 5 6) ;this function takes any number of arguments </I><BR>18 <BR>><I> (+ (+ 3 4) (+ (+ 4 5) 6)) ;isn't prefix notation fun? </I><BR>22 <BR>><I> (defun foo (x y) (+ x y 5)) ;defining a function </I><BR>FOO <BR>><I> (foo 5 0) ;calling a function </I><BR>10 <BR>><I> (defun fact (x) ;a recursive function </I><BR> (if (> x 0) <BR> (* x (fact (- x 1))) <BR> 1 <BR> ) ) <BR>FACT <BR>><I> (fact 5) </I><BR>120 <BR>><I> (defun a (x) (if (= x 0) t (b (- x)))) ;mutually recursive functions </I><BR>A <BR>><I> (defun b (x) (if (> x 0) (a (- x 1)) (a (+ x 1)))) </I><BR>B <BR>><I> (a 5) </I><BR>T <BR>><I> (defun bar (x) ;a function with multiple statements in </I><BR> (setq x (* x 3)) ;its body -- it will return the value <BR> (setq x (/ x 2)) ;returned by its final statement <BR> (+ x 4) <BR> ) <BR>BAR <BR>><I> (bar 6) </I><BR>13 <BR> <BR>When we defined foo, we gave it two arguments, x and y. Now when we <BR>call foo, we are required to provide exactly two arguments: the first <BR>will become the value of x for the duration of the call to foo, and the <BR>second will become the value of y for the duration of the call. In <BR>LISP, most variables are lexically scoped; that is, if foo calls bar <BR>and bar tries to reference x, bar will not get foo's value for x. <BR> <BR>The process of assigning a symbol a value for the duration of some <BR>lexical scope is called binding. <BR> <BR>You can specify optional arguments for your functions. Any argument <BR>after the symbol &optional is optional: <BR> <BR>><I> (defun bar (x &optional y) (if y x 0)) </I><BR>BAR <BR>><I> (defun baaz (&optional (x 3) (z 10)) (+ x z)) </I><BR>BAAZ <BR>><I> (bar 5) </I><BR>0 <BR>><I> (bar 5 t) </I><BR>5 <BR>><I> (baaz 5) </I><BR>15 <BR>><I> (baaz 5 6) </I><BR>11 <BR>><I> (baaz) </I><BR>13 <BR> <BR>It is legal to call the function bar with either one or two arguments. <BR>If it is called with one argument, x will be bound to the value of that <BR>argument and y will be bound to nil; if it is called with two <BR>arguments, x and y will be bound to the values of the first and second <BR>argument, respectively. <BR> <BR>The function baaz has two optional arguments. It specifies a default <BR>value for each of them: if the caller specifies only one argument, z <BR>will be bound to 10 instead of to nil, and if the caller specifies no <BR>arguments, x will be bound to 3 and z to 10. <BR> <BR>You can make your function accept any number of arguments by ending its <BR>argument list with an &rest parameter. LISP will collect all arguments <BR>not otherwise accounted for into a list and bind the &rest parameter to <BR>that list. So: <BR> <BR>><I> (defun foo (x &rest y) y) </I><BR>FOO <BR>><I> (foo 3) </I><BR>NIL <BR>><I> (foo 4 5 6) </I><BR>(5 6) <BR> <BR>Finally, you can give your function another kind of optional argument <BR>called a keyword argument. The caller can give these arguments in any <BR>order, because they're labelled with keywords. <BR> <BR>><I> (defun foo (&key x y) (cons x y)) </I><BR>FOO <BR>><I> (foo :x 5 :y 3) </I><BR>(5 . 3) <BR>><I> (foo :y 3 :x 5) </I><BR>(5 . 3) <BR>><I> (foo :y 3) </I><BR>(NIL . 3) <BR>><I> (foo) </I><BR>(NIL) <BR> <BR>An &key parameter can have a default value too: <BR> <BR>><I> (defun foo (&key (x 5)) x) </I><BR>FOO <BR>><I> (foo :x 7) </I><BR>7 <BR>><I> (foo) </I><BR>5 <BR> <BR> <BR> <BR>Printing <BR> <BR>Some functions can cause output. The simplest one is print, which <BR>prints its argument and then returns it. <BR> <BR>><I> (print 3) </I><BR>3 <BR>3 <BR> <BR>The first 3 above was printed, the second was returned. <BR> <BR>If you want more complicated output, you will need to use format. <BR>Here's an example: <BR> <BR>><I> (format t "An atom: ~S~%and a list: ~S~%and an integer: ~D~%" </I><BR> nil (list 5) 6) <BR>An atom: NIL <BR>and a list: (5) <BR>and an integer: 6 <BR> <BR>The first argument to format is either t, nil, or a stream. T specifies <BR>output to the terminal. Nil means not to print anything but to return a <BR>string containing the output instead. Streams are general places for <BR>output to go: they can specify a file, or the terminal, or another <BR>program. This handout will not describe streams in any further detail. <BR> <BR>The second argument is a formatting template, which is a string <BR>optionally containing formatting directives. <BR> <BR>All remaining arguments may be referred to by the formatting <BR>directives. LISP will replace the directives with some appropriate <BR>characters based on the arguments to which they refer and then print <BR>the resulting string. <BR> <BR>Format always returns nil unless its first argument is nil, in which <BR>case it prints nothing and returns a string. <BR> <BR>There are three different directives in the above example: ~S, ~D, and <BR>~%. The first one accepts any LISP object and is replaced by a printed <BR>representation of that object (the same representation which is <BR>produced by print). The second one accepts only integers. The third one <BR>doesn't refer to an argument; it is always replaced by a carriage <BR>return. <BR> <BR>Another useful directive is ~~, which is replaced by a single ~. <BR> <BR>Refer to a LISP manual for (many, many) additional formatting <BR>directives. <BR> <BR> <BR> <BR>Forms and the Top-Level Loop <BR> <BR>The things which you type to the LISP interpreter are called forms; the <BR>LISP interpreter repeatedly reads a form, evaluates it, and prints the <BR>result. This procedure is called the read-eval-print loop. <BR> <BR>Some forms will cause errors. After an error, LISP will put you into <BR>the debugger so you can try to figure out what caused the error. LISP <BR>debuggers are all different; but most will respond to the command <BR>"help" or ":help" by giving some form of help. <BR> <BR>In general, a form is either an atom (for example, a symbol, an <BR>integer, or a string) or a list. If the form is an atom, LISP evaluates <BR>it immediately. Symbols evaluate to their value; integers and strings <BR>evaluate to themselves. If the form is a list, LISP treats its first <BR>element as the name of a function; it evaluates the remaining elements <BR>recursively, and then calls the function with the values of the <BR>remaining elements as arguments. <BR> <BR>For example, if LISP sees the form (+ 3 4), it treats + as the name of <BR>a function. It then evaluates 3 to get 3 and 4 to get 4; finally it <BR>calls + with 3 and 4 as the arguments. The + function returns 7, which <BR>LISP prints. <BR> <BR>The top-level loop provides some other conveniences; one particularly <BR>convenient convenience is the ability to talk about the results of <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -