分享
 
 
 

CLIST Tutorial中英对照版(二)

王朝other·作者佚名  2006-04-03
窄屏简体版  字體: |||超大  

Forms and the Top-Level Loop

The things which you type to the LISP interpreter are called forms; the

LISP interpreter repeatedly reads a form, evaluates it, and prints the

result. This procedure is called the read-eval-print loop.

我们输入到LISP解释器的东西被称为语句;LISP解释器逐条循环读取每条语句,

进行解析,将结果打印出来。这个过程被称为读取-解析-打印循环。

Some forms will cause errors. After an error, LISP will put you into

the debugger so you can try to figure out what caused the error. LISP

debuggers are all different; but most will respond to the command

"help" or ":help" by giving some form of help.

某些语句会发生错误,LISP会引领我们进入调试器,以便我们找出错误原因。

LISP的各种调试器有很多差异,不过使用"help"或":help"命令就会给出一

些语句帮助。

In general, a form is either an atom (for example, a symbol, an

integer, or a string) or a list. If the form is an atom, LISP evaluates

it immediately. Symbols evaluate to their value; integers and strings

evaluate to themselves. If the form is a list, LISP treats its first

element as the name of a function; it evaluates the remaining elements

recursively, and then calls the function with the values of the

remaining elements as arguments.

通常,一个语句是一个原子(例如,一个符号或者整数,或者字符串)或者一个列表,

如果换某个语句是原子,LISP立即解析它。符号解析为它们的值;整数和字符串解析

为它们自身。如果语句是一个列表,LISP视它的第一个元素为函数名;它递归的解析

其余的元素,然后将它们的值作为参数来调用这个函数。

For example, if LISP sees the form (+ 3 4), it treats + as the name of

a function. It then evaluates 3 to get 3 and 4 to get 4; finally it

calls + with 3 and 4 as the arguments. The + function returns 7, which

LISP prints.

例如,如果LISP遇到语句 (+ 3 4),它尝试将 + 作为函数名。然后将3解析为3,4解

析为4;最后用3和4作为参数调用+。LISP打印出 + 函数的返回值7。

The top-level loop provides some other conveniences; one particularly

convenient convenience is the ability to talk about the results of

previously typed forms. LISP always saves its most recent three

results; it stores them as the values of the symbols *, **, and ***.

For example:

顶级循环还提供了一些其它的便利;一个特别方便的地方就是获取以前 输入的

语句的结果。LISP总会保存最近三个结果;它将它们保存在*,**和***三个符

号的值中,例如:

> 3

3

> 4

4

> 5

5

> ***

3

> ***

4

> ***

5

> **

4

> *

4

Special forms

There are a number of special forms which look like function calls but

aren't. These include control constructs such as if statements and do

loops; assignments like setq, setf, push, and pop; definitions such as

defun and defstruct; and binding constructs such as let. (Not all of

these special forms have been mentioned yet. See below.)

有几个特殊语句看起来像函数调用,但其实不是。这里面包括流程控制语句,例

如 if 语句和 do loops;赋值语句,例如 setq, setf,push和pop;定义语句

例如 defun 和 defstruct;以及绑定构造,如 let。(这里没有提及所有的特殊

语句。我们继续。)

One useful special form is the quote form: quote prevents its argument

from being evaluated. For example:

一个很有用的特殊语句是 quote :quote取消其参数的绑定状态。例如:

> (setq a 3)

3

> a

3

> (quote a)

A

> 'a ;'a is an abbreviation for (quote a)

A

Another similar special form is the function form: function causes its

argument to be interpreted as a function rather than being evaluated.

For example:

另一个类似的语句是 fuction:function使得解释器将其参数视为一个函数而不是

解析值,例如:

> (setq + 3)

3

> +

3

> '+

+

> (function +)

#<Function + @ #x-fbef9de>

> #'+ ;#'+ is an abbreviation for (function +)

#<Function + @ #x-fbef9de>

The function special form is useful when you want to pass a function as

an argument to another function. See below for some examples of

functions which take functions as arguments.

当我们需要将一个函数作为参数传递给另一个函数时会用到 function 语句。后面

有些示例函数将函数作为参数。

Binding

Binding is lexically scoped assignment. It happens to the variables in

a function's parameter list whenever the function is called: the formal

parameters are bound to the actual parameters for the duration of the

function call. You can bind variables anywhere in a program with the

let special form, which looks like this:

绑定是词汇作用域赋值(汗,怎么读怎么别扭——译者)。每当函数调用时,它就

发生于函数的参数列变量中:形式参数被取代为调用函数时的实际参数。你可以在

程序中随处绑定变量,就像下面这样:

(let ((var1 val1)

(var2 val2)

...)

body)

Let binds var1 to val1, var2 to val2, and so forth; then it executes

the statements in its body. The body of a let follows exactly the same

rules that a function body does. Some examples:

let把val1绑定到var1,把val2绑定到var2,依次类推;然后在它的程序体中执

行语句。let的程序体与函数体的执行规则完全相同。例如:

> (let ((a 3)) (+ a 1))

4

> (let ((a 2)

(b 3)

(c 0))

(setq c (+ a b))

c)

5

> (setq c 4)

4

> (let ((c 5)) c)

5

> c

4

Instead of (let ((a nil) (b nil)) ...), you can write (let (a b) ...).

你可以用 (let (a b) ...) 代替 (let ((a nil) (b nil)) ...) 。

The val1, val2, etc. inside a let cannot reference the variables var1,

var2, etc. that the let is binding. For example,

val1,val2等等。在 let 内部不能引用 var1,var2等等let正在绑定的成员。

例如(简而言之,在参数表中,形式参数之间不能互相引用——译者):

> (let ((x 1)

(y (+ x 1)))

y)

Error: Attempt to take the value of the unbound symbol X

If the symbol x already has a global value, stranger happenings will

result:

如果符号x已经有了一个全局值,会产生一些奇怪的结果:

> (setq x 7)

7

> (let ((x 1)

(y (+ x 1)))

y)

8

The let* special form is just like let except that it allows values to

reference variables defined earlier in the let*. For example,

let* 语句类似于 let,但它允许引用之前在 let* 中定义的变量的值。例如:

> (setq x 7)

7

> (let* ((x 1)

(y (+ x 1)))

y)

2

The form

语句

(let* ((x a)

(y b))

...)

is equivalent to

等价于

(let ((x a))

(let ((y b))

...))

Dynamic Scoping

The let and let* forms provide lexical scoping, which is what you

expect if you're used to programming in C or Pascal. Dynamic scoping is

what you get in BASIC: if you assign a value to a dynamically scoped

variable, every mention of that variable returns that value until you

assign another value to the same variable.

与我们在C或Pascal中编写程序不同,let 和 let* 语句提供了词汇作用域。动态

作用域是我们在BASIC里用的那种:如果我们给一个动态作用域变量赋了值,那么

所有对这个变量的访问都会取得这个值,直到给同一个变量赋了另一个值为止。

In LISP, dynamically scoped variables are called special variables. You

can declare a special variable with the defvar special form. Here are

some examples of lexically and dynamically scoped variables.

在LISP中,动态作用域变量被称为特化变量 。你可以用 special 语句 defvar

定义一个特化变量。这里有一些词汇化和动态作用域变量的示例。

In this example, the function check-regular references a regular (ie,

lexically scoped) variable. Since check-regular is lexically outside of

the let which binds regular, check-regular returns the variable's

global value.

在以下示例中,check-regular 函数引用一个 regular (也就是一个词汇作用域)

变量。因为 check-regular 在绑定 regular 的 let 外部词汇化,check-regular

返回变量的全局值。

> (setq regular 5)

5

> (defun check-regular () regular)

CHECK-REGULAR

> (check-regular)

5

> (let ((regular 6)) (check-regular))

5

In this example, the function check-special references a special (ie,

dynamically scoped) variable. Since the call to check-special is

temporally inside of the let which binds special, check-special returns

the variable's local value.

在这个例子中,函数 check-special 引用了一个 特化(动态作用域)变量。

因此 check-special 调用临时发生于特化绑定的 let 内部,check-special

返回变量的局部值。

> (defvar *special* 5)

*SPECIAL*

> (defun check-special () *special*)

CHECK-SPECIAL

> (check-special)

5

> (let ((*special* 6)) (check-special))

6

By convention, the name of a special variable begins and ends with a *.

Special variables are chiefly used as global variables, since

programmers usually expect lexical scoping for local variables and

dynamic scoping for global variables.

方便起见,特化变量以一个 * 开始和结束。特化变量主要用于全局变量,因为

程序员通常期望局部变量使用词汇作用域,全局变量使用动态作用域。

For more information on the difference between lexical and dynamic

scoping, see _Common LISP: the Language_.

词汇和动态作用域的更多差异参见《Common LISP: the Language》。

Arrays

The function make-array makes an array. The aref function accesses its

elements. All elements of an array are initially set to nil. For

example:

make-array 函数定义一个数组。aref 函数访问它的元素。所有元素初始化为nil。

例如:

> (make-array '(3 3))

#2a((NIL NIL NIL) (NIL NIL NIL) (NIL NIL NIL))

> (aref * 1 1)

NIL

> (make-array 4) ;1D arrays don't need the extra parens

#(NIL NIL NIL NIL)

Array indices always start at 0.

数组索引从0开始。

See below for how to set the elements of an array.

以后讨论如何设置一个数组的元素。

Strings

A string is a sequence of characters between double quotes. LISP

represents a string as a variable-length array of characters. You can

write a string which contains a double quote by preceding the quote

with a backslash; a double backslash stands for a single backslash. For

example:

字符串是包含在双引号之间的字符串。LISP 用字符串代表一个变长字符数组。

我们可以用一个反斜杠加一个双引号来表示字符串中的双引号,两个反斜杠表示

一个单独的反斜杠。例如:

"abcd" has 4 characters

"\"" has 1 character

"\\" has 1 character

Here are some functions for dealing with strings:

有一些函数可以用于操作字符串:

> (concatenate 'string "abcd" "efg")

"abcdefg"

> (char "abc" 1)

#\b ;LISP writes characters preceded by #\

> (aref "abc" 1)

#\b ;remember, strings are really arrays

The concatenate function can actually work with any type of sequence:

concatenate 函数可以用于连接任何类型的序列:

> (concatenate 'string '(#\a #\b) '(#\c))

"abc"

> (concatenate 'list "abc" "de")

(#\a #\b #\c #\d #\e)

> (concatenate 'vector '#(3 3 3) '#(3 3 3))

#(3 3 3 3 3 3)

Structures

LISP structures are analogous to C structs or Pascal records. Here is

an example:

LISP 结构类似于C结构或Pasacal记录。如下所示:

> (defstruct foo

bar

baaz

quux)

FOO

This example defines a data type called foo which is a structure

containing 3 fields. It also defines 4 functions which operate on this

data type: make-foo, foo-bar, foo-baaz, and foo-quux. The first one

makes a new object of type foo; the others access the fields of an

object of type foo. Here is how to use these functions:

这个示例定义了一个名为 foo 的数据类型,它是一个带有三个字段的结构。

它同时定义了4个函数用于操作这个数据类型:make-foo,foo-ba,foo-baaz和

foo-quux。第一个函数构造了一个foo类型的新对象,另外三个用于访问一个

foo类型的对象。以下是这些函数的用法:

> (make-foo)

#s(FOO :BAR NIL :BAAZ NIL :QUUX NIL)

> (make-foo :baaz 3)

#s(FOO :BAR NIL :BAAZ 3 :QUUX NIL)

> (foo-bar *)

NIL

> (foo-baaz **)

3

The make-foo function can take a keyword argument for each of the

fields a structure of type foo can have. The field access functions

each take one argument, a structure of type foo, and return the

appropriate field.

meke-foo 函数可以使用foo结构类型的字段作为关键字参数。字段访问函数以

foo类型的结构为参数,返回对应的字段。

See below for how to set the fields of a structure.

以后讨论如何设置一个结构的字段。

Setf

Certain forms in LISP naturally define a memory location. For example,

if the value of x is a structure of type foo, then (foo-bar x) defines

the bar field of the value of x. Or, if the value of y is a one-

dimensional array, (aref y 2) defines the third element of y.

LISP确认语句的时间,自然就会定义一个内存区域。例如,如果x的值是foo类型

的一个结构,(foo-bar x)定义x中bar字段的值。或者,如果y是一个一维数组,

(aref y 2)定义y的第三个元素。

The setf special form uses its first argument to define a place in

memory, evaluates its second argument, and stores the resulting value

in the resulting memory location. For example,

setf 语句用于在内存中将它的第一个参数定位到第二个参数上,并且返回内存

区域的结果值。例如:

> (setq a (make-array 3))

#(NIL NIL NIL)

> (aref a 1)

NIL

> (setf (aref a 1) 3)

3

> a

#(NIL 3 NIL)

> (aref a 1)

3

> (defstruct foo bar)

FOO

> (setq a (make-foo))

#s(FOO :BAR NIL)

> (foo-bar a)

NIL

> (setf (foo-bar a) 3)

3

> a

#s(FOO :BAR 3)

> (foo-bar a)

3

Setf is the only way to set the fields of a structure or the elements

of an array.

setf是给结构的字段或者数组的元素赋值的唯一方法。

Here are some more examples of setf and related functions.

这里还有一些关于setf和相关函数的示例。

> (setf a (make-array 1)) ;setf on a variable is equivalent to setq

#(NIL)

> (push 5 (aref a 1)) ;push can act like setf

(5)

> (pop (aref a 1)) ;so can pop

5

> (setf (aref a 1) 5)

5

> (incf (aref a 1)) ;incf reads from a place, increments,

6 ;and writes back

> (aref a 1)

6

Booleans and Conditionals

LISP uses the self-evaluating symbol nil to mean false. Anything other

than nil means true. Unless we have a reason not to, we usually use the

self-evaluating symbol t to stand for true.

LISP 用自解析符号 nil 来代表 false。任何 nil 之外的其它东西都代表 true。

除非有什么特别的原因,我们总是使用 true 的标准自解析符号 t。

LISP provides a standard set of logical functions, for example and, or,

and not. The and and or connectives are short-circuiting: and will not

evaluate any arguments to the right of the first one which evaluates to

nil, while or will not evaluate any arguments to the right of the first

one which evaluates to t.

LISP提供了一个逻辑运算的标准函数集,例如,与、或、非。与和或支持短路算法:

在遇到第一个nil后不再解析右面的参数,而与在遇到第一个t后也不再解析右面的

参数。

LISP also provides several special forms for conditional execution. The

simplest of these is if. The first argument of if determines whether

the second or third argument will be executed:

LISP还为条件控制提供了几个特殊语句。最简单的是if。if语句的第一个参数决定了

执行第二或第三个参数中的哪一个:

> (if t 5 6)

5

> (if nil 5 6)

6

> (if 4 5 6)

5

If you need to put more than one statement in the then or else clause

of an if statement, you can use the progn special form. Progn executes

each statement in its body, then returns the value of the final one.

如果你需要在then或else块中放置超过一行的语句,可以使用特殊语句 progn。

Progn 在它的程序体内依次执行每一条语句,返回最后一个结果。

> (setq a 7)

7

> (setq b 0)

0

> (setq c 5)

5

> (if (> a 5)

(progn

(setq a (+ b 7))

(setq b (+ c 8)))

(setq b 4))

13

An if statement which lacks either a then or an else clause can be

written using the when or unless special form:

一个没有 else 或 when 的语句可以写为 when 或 unless 语句。

> (when t 3)

3

> (when nil 3)

NIL

> (unless t 3)

NIL

> (unless nil 3)

3

When and unless, unlike if, allow any number of statements in their

bodies. (Eg, (when x a b c) is equivalent to (if x (progn a b c)).)

与 if 不同,when 和 unless 允许在程序体内放置任意多的语句。(例如,

(when x a b c) 等价于 (if x (progn a b c)))

> (when t

(setq a 5)

(+ a 6))

11

More complicated conditionals can be defined using the cond special

form, which is equivalent to an if ... else if ... fi construction.

更复杂的条件控制可以用 cond 语句定义实现,它定价于一个 if ... else

if ... fi 条件。

A cond consists of the symbol cond followed by a number of cond

clauses, each of which is a list. The first element of a cond clause is

the condition; the remaining elements (if any) are the action. The cond

form finds the first clause whose condition evaluates to true (ie,

doesn't evaluate to nil); it then executes the corresponding action and

returns the resulting value. None of the remaining conditions are

evaluated; nor are any actions except the one corresponding to the

selected condition. For example:

一个 cond 由 symbol 符号和其后的若干条件分支组成,每一个分支是一个 list。

cond 分支的第一个元素是条件;其它的元素(如果有的话)是动作。cond语句查

找第一个条件解析为 true 的分支,执行其响应动作并返回结果值。其它条件不会

被解析,除了这个响应之外的分支也不会执行。例如:

> (setq a 3)

3

> (cond

((evenp a) a) ;if a is even return a

((> a 7) (/ a 2)) ;else if a is bigger than 7 return a/2

((< a 5) (- a 1)) ;else if a is smaller than 5 return a-1

(t 17)) ;else return 17

2

If the action in the selected cond clause is missing, cond returns what

the condition evaluated to:

如果选定的分支没有响应动作,cond 返回条件的解析结果。

> (cond ((+ 3 4)))

7

Here's a clever little recursive function which uses cond. You might be

interested in trying to prove that it terminates for all integers x at

least 1. (If you succeed, please publish the result.)

这里用 cond 巧妙的实现了一个递归函数。你可能会有兴趣证明它对于所有的整数

x 都少有个终结。(如果你成功了,请发表出来。)

> (defun hotpo (x steps) ;hotpo stands for Half Or Triple Plus One

(cond

((= x 1) steps)

((oddp x) (hotpo (+ 1 (* x 3)) (+ 1 steps)))

(t (hotpo (/ x 2) (+ 1 steps)))))

A

> (hotpo 7 0)

16

The LISP case statement is like a C switch statement:

LISP 的 case 语句类似于 C 的 switch 语句:

> (setq x 'b)

B

> (case x

(a 5)

((d e) 7)

((b f) 3)

(otherwise 9))

3

The otherwise clause at the end means that if x is not a, b, d, e, or

f, the case statement will return 9.

末尾的 otherwise 语句意味着 x 不是a、b、c、d、e、f,case语句将会返回9。

Iteration

The simplest iteration construct in LISP is loop: a loop construct

repeatedly executes its body until it hits a return special form. For

example,

LISP 中最简单的迭代结构是 loop:loop 结构反复执行它的程序体直到到达

一个返回语句,例如:

> (setq a 4)

4

> (loop

(setq a (+ a 1))

(when (> a 7) (return a)))

8

> (loop

(setq a (- a 1))

(when (< a 3) (return)))

NIL

The next simplest is dolist: dolist binds a variable to the elements of

a list in order and stops when it hits the end of the list.

dolist是下一个最简单的:dolist把一个变量依次绑定到一个列表的各个元素上,

在到达列表结尾时结束。

> (dolist (x '(a b c)) (print x))

A

B

C

NIL

Dolist always returns nil. Note that the value of x in the above

example was never nil: the NIL below the C was the value that dolist

returned, printed by the read-eval-print loop.

Dolist 总是返回nil。注意上例中的 x 永远不会为nil:C后面的NIL是dolist

返回的,它被读取-解析-打印循环所打印。

The most complicated iteration primitive is called do. A do statement

looks like this:

更复杂的迭代称为 do。do语句的示例如下:

> (do ((x 1 (+ x 1))

(y 1 (* y 2)))

((> x 5) y)

(print y)

(print 'working))

1

WORKING

2

WORKING

4

WORKING

8

WORKING

16

WORKING

32

The first part of a do specifies what variables to bind, what their

initial values are, and how to update them. The second part specifies a

termination condition and a return value. The last part is the body. A

do form binds its variables to their initial values like a let, then

checks the termination condition. As long as the condition is false, it

executes the body repeatedly; when the condition becomes true, it

returns the value of the return-value form.

do的第一步是指定绑定的变量,它们的初始值,以及如何更新。第二步是指定一

个终止条件和返回值。最后是程序体。do语句像let一样把它的变量绑定到初始值,

然后校验终止条件。条件为false时,它重复执行程序体;当条件为true,它返回

return-value 语句的值。

The do* form is to do as let* is to let.

do* 语句之于 do 如同 let* 之于 let。

Non-local Exits

The return special form mentioned in the section on iteration is an

example of a nonlocal return. Another example is the return-from form,

which returns a value from the surrounding function:

前一节中迭代示例里的renturn语句是一个无定位返回的示例,另一个是

return-from,它从包围它的函数中返回指定值。

> (defun foo (x)

(return-from foo 3)

x)

FOO

> (foo 17)

3

Actually, the return-from form can return from any named block -- it's

just that functions are the only blocks which are named by default. You

can create a named block with the block special form:

实际上,return-from 语句可以从任何已命名的语句块中退出——只是默认情况下

函数是唯一的命名语句块而已。我们可以用 block 语句自己定义一个命名语句块。

> (block foo

(return-from foo 7)

3)

7

The return special form can return from any block named nil. Loops are

by default labelled nil, but you can make your own nil-labelled blocks:

return 语句可以从任何nil命名的语句块中返回。默认情况下循环是nil命名,而

我们可以创建自己的nil标记语句块。

> (block nil

(return 7)

3)

7

Another form which causes a nonlocal exit is the error form:

另外一个无定位退出语句是 error 语句:

> (error "This is an error")

Error: This is an error

The error form applies format to its arguments, then places you in the

debugger.

error语句格式化它的参数,然后进入调试器。

Funcall, Apply, and Mapcar

Earlier I promised to give some functions which take functions as

arguments. Here they are:

早先我承诺介绍一些可以将函数作为参数调用函数,它们在这里:

> (funcall #'+ 3 4)

7

> (apply #'+ 3 4 '(3 4))

14

> (mapcar #'not '(t nil t nil t nil))

(NIL T NIL T NIL T)

Funcall calls its first argument on its remaining arguments.

funcall 用它的其它参数调用它的第一个参数。

Apply is just like funcall, except that its final argument should be a

list; the elements of that list are treated as if they were additional

arguments to a funcall.

Apply和funcall很相像,不过它的最后一个参数可以是一个列表;这个列表被看

作是funcall的附加参数。

The first argument to mapcar must be a function of one argument; mapcar

applies this function to each element of a list and collects the

results in another list.

mapcar的第一个参数必须是一个单参数的函数;mapcar在列表上逐个元素应用该

函数,并将返回值包含如另一个链表。

Funcall and apply are chiefly useful when their first argument is a

variable. For instance, a search engine could take a heuristic function

as a parameter and use funcall or apply to call that function on a

state description. The sorting functions described later use funcall

to call their comparison functions.

Funcall和apply主要用于第一个参数是变量的场合。例如,搜索引擎把一个启发式

函数作为参数,在一个状态描述上应用funcall或者apply。

Mapcar, along with nameless functions (see below), can replace many

loops.

Mapcar配合匿名函数(后面介绍),可以取代很多循环。

Lambda

If you just want to create a temporary function and don't want to

bother giving it a name, lambda is what you need.

如果你只是想创建一个临时函数,并不想给它一个命名,lambda如你所愿。

> #'(lambda (x) (+ x 3))

(LAMBDA (X) (+ X 3))

> (funcall * 5)

8

The combination of lambda and mapcar can replace many loops. For

example, the following two forms are equivalent:

lambda和mapcar的组合可以取代很多循环,例如,如下的两个语句是等价的:

> (do ((x '(1 2 3 4 5) (cdr x))

(y nil))

((null x) (reverse y))

(push (+ (car x) 2) y))

(3 4 5 6 7)

> (mapcar #'(lambda (x) (+ x 2)) '(1 2 3 4 5))

(3 4 5 6 7)

Sorting

LISP provides two primitives for sorting: sort and stable-sort.

LISP提供两种主要的排序:排序和稳定排序。

> (sort '(2 1 5 4 6) #'<)

(1 2 4 5 6)

> (sort '(2 1 5 4 6) #'>)

(6 5 4 2 1)

The first argument to sort is a list; the second is a comparison

function. The sort function does not guarantee stability: if there are

two elements a and b such that (and (not (< a b)) (not (< b a))), sort

may arrange them in either order. The stable-sort function is exactly

like sort, except that it guarantees that two equivalent elements

appear in the sorted list in the same order that they appeared in the

original list.

sort的第一个参数是一个列表,第二个是一个比较函数。sort函数不保证稳定性:

如果这里有a和b两个元素,(and (not (< a b)) (not (< b a))),sort可能会改

变它们的位置。stable-sort(稳定排序)与sort非常像,不过它确保两个相等

的元素在排序后的列表中的顺序与排序前列表中的顺序相同。

Be careful: sort is allowed to destroy its argument, so if the original

sequence is important to you, make a copy with the copy-list or copy-seq

function.

注意:sort可能会破坏它的参数,如果原始序列对我们很重要,最好使用copy-list

或copy-seq函数创建一个副本。

Equality

LISP has many different ideas of equality. Numerical equality is

denoted by =. Two symbols are eq if and only if they are identical. Two

copies of the same list are not eq, but they are equal.

关于相等,LISP有很多不同的观点。数值相等意味着=。两个符号当且仅当他们完全

一样时相同。同一个列表的两个副本不相同,但是它们相等。

> (eq 'a 'a)

T

> (eq 'a 'b)

NIL

> (= 3 4)

NIL

> (eq '(a b c) '(a b c))

NIL

> (equal '(a b c) '(a b c))

T

> (eql 'a 'a)

T

> (eql 3 3)

T

The eql predicate is equivalent to eq for symbols and to = for numbers

or the same type:

谓词eql代表相等,它对于符号表示相同,对于数值表示=。

> (eql 2.0 2)

NIL

> (= 2.0 2)

T

> (eq 12345678901234567890 12345678901234567890)

NIL

> (= 12345678901234567890 12345678901234567890)

T

> (eql 12345678901234567890 12345678901234567890)

T

The equal predicate is equivalent to eql for symbols and numbers. It is

true for two conses if and only if their cars are equal and their cdrs

are equal. It is true for two structures if and only if the structures

are the same type and their corresponding fields are equal.

equal谓词对于符号和数值是相等。当且仅当两个 conse 的car和cdr都相等时它们

才是相等的。当且仅当两个结构是同类型而且各字段都相等时它们相等。

Some Useful List Functions

These functions all manipulate lists.

这些函数都用来操作列表。

> (append '(1 2 3) '(4 5 6)) ;concatenate lists

(1 2 3 4 5 6)

> (reverse '(1 2 3)) ;reverse the elements of a list

(3 2 1)

> (member 'a '(b d a c)) ;set membership -- returns the first tail

(A C) ;whose car is the desired element

> (find 'a '(b d a c)) ;another way to do set membership

A

> (find '(a b) '((a d) (a d e) (a b d e) ()) :test #'subsetp)

(A B D E) ;find is more flexible though

> (subsetp '(a b) '(a d e)) ;set containment

NIL

> (intersection '(a b c) '(b)) ;set intersection

(B)

> (union '(a) '(b)) ;set union

(A B)

> (set-difference '(a b) '(a)) ;set difference

(B)

Subsetp, intersection, union, and set-difference all assume that each

argument contains no duplicate elements -- (subsetp '(a a) '(a b b)) is

allowed to fail, for example.

Subsetp,intersection,union和set-difference都允许各个参数包含不匹配的元素

——例如,(subsetp '(a a) '(a b b))可以为fail。

Find, subsetp, intersection, union, and set-difference can all take a

:test keyword argument; by default, they all use eql.

Find,subsetp,intersection,union和set-difference都可以接受一个:test关键

字参数;默认情况下,它们是等价的。

Getting Started with Emacs

You can use Emacs to edit LISP code: most Emacses are set up to enter

LISP mode automatically when they find a file which ends in .lisp, but

if yours isn't, you can type M-x lisp-mode.

你可以使用Emacs编辑LISP代码:Emaces在打开.lisp文件时总会自动进入LISP模式,

不过如果我们的Emacs没有成功进入这个状态,可以通过输入M-x lisp-mode做到。

You can run LISP under Emacs, too: make sure that there is a command in

your path called "lisp" which runs your favorite LISP. For example, you

could type

我们也可以在Emacs下运行LISP:先确保在我们的私人路径下可以运行一个叫

"LISP"的命令。例如,我们可以输入:

ln -s /usr/local/bin/clisp ~/bin/lisp

Then in Emacs type M-x run-lisp. You can send LISP code to the LISP you

just started, and do all sorts of other cool things; for more

information, type C-h m from any buffer which is in LISP mode.

然后在Emacs中输入 M-x run-lip。我们可以向LISP发送先前的LISP代码,做其它

很酷的事情;在LISP模式下的任何缓冲输入 C-h m可以得到进一步的信息。

Actually, you don't even need to make a link. Emacs has a variable

called inferior-lisp-program; so if you add the line

实际上,我们甚至不需要建立链接。Emacs有一个变量叫 inferior-lisp-program;

所以我们可以把下面这行

(setq inferior-lisp-program "/usr/local/bin/clisp")

to your .emacs file, Emacs will know where to find CLISP when

you type M-x run-lisp.

输入到自己的 .emacs 文件中,Emacs就会知道在你输入 M-x run-lisp时去哪里寻找

CLISP。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有