Lisp是如何实现的;prog";在这个例子中工作?
我是lisp的初学者,我需要有人一步一步地向我解释Lisp是如何实现的;prog";在这个例子中工作?,lisp,common-lisp,Lisp,Common Lisp,我是lisp的初学者,我需要有人一步一步地向我解释prog表单是如何工作的。l1的初始值是多少?零 如果列表在第一级上有偶数个元素,则问题输出T,否则输出nil (defun nr_par (l) (prog ((l1 l)) ciclu (cond ((null l1) (return T)) ((null (cdr l1)) (return NIL)) ((null (cddr l1)) (return T)) (T (se
prog
表单是如何工作的。l1的初始值是多少?零
如果列表在第一级上有偶数个元素,则问题输出T,否则输出nil
(defun nr_par (l)
(prog ((l1 l))
ciclu
(cond
((null l1) (return T))
((null (cdr l1)) (return NIL))
((null (cddr l1)) (return T))
(T (setf l1 (cddr l1))
(go ciclu)))))
在控制台上:
(nr_par '(1 2 3 4 5 6 7 8))
T
请参见:
L1
是var,L
是init form,因此L1
的初始值是L
的值。请参见:L1
是var,L
是init form,因此L1
的初始值是L
的值。该程序很简单,但不是非常地道的lisp>(这是非常必要的,而不是功能性的)
prog
使用一系列变量绑定,在这种情况下,l1
最初被分配l
的值。然后,循环开始的一系列语句(同样,不是非常lisp惯用)
这种类型的循环使用一个标记(ciclu
)和一个goto指令(go
),同样不推荐使用,但它确实存在。之后,cond
检查一系列情况。当列表为空(null
),则返回true,在其他情况下,检查长度是偶数还是奇数,然后返回结果值
如果列表长度超过一个或两个元素(两种情况均不为空),则调整l1
列表以指向其自身的下一个元素(函数cddr
)
最后,go
函数将程序返回到ciclu
标记
当满足任何cond
子句时,程序将完成,返回T
或NIL
程序很简单,但不是非常惯用的lisp(它是命令式的,而不是函数式的)
prog
使用一系列变量绑定,在这种情况下,l1
最初被分配l
的值。然后,循环开始的一系列语句(同样,不是非常lisp惯用)
这种类型的循环使用一个标记(ciclu
)和一个goto指令(go
),同样不推荐使用,但它确实存在。之后,cond
检查一系列情况。当列表为空(null
),则返回true,在其他情况下,检查长度是偶数还是奇数,然后返回结果值
如果列表长度超过一个或两个元素(两种情况均不为空),则调整l1
列表以指向其自身的下一个元素(函数cddr
)
最后,go
函数将程序返回到ciclu
标记
当满足任何cond
子句时,程序将完成,返回T
或NIL
,如上所述,它可以做三件事:让您拥有本地变量并初始化它们;让您拥有标签,如tagbody
和使用go
;让您在块中使用返回
de>命名为NIL
:
(defun nr_par (l)
(prog ((l1 l)) ; local binding(s)
ciclu
(if (null l1) (return T)) ; return
(if (null (cdr l1)) (return NIL))
(setf l1 (cddr l1))
(go ciclu))) ; go
(defun nr_par1 (l) ; directly equivalent
(labels ((ciclu (l1)
(if (null l1) (return-from ciclu T))
(if (null (cdr l1)) (return-from ciclu NIL))
(ciclu (cddr l1))))
(ciclu l)))
(defun nr_par2 (l) ; also equivalent
(do ((l1 l (cddr l1)))
(NIL) ; while T ...
(cond
((null l1) (return T))
((null (cdr l1)) (return NIL)))))
函数调用毕竟是一个美化的goto
,不是吗
另请参见一个示例,该示例表示几个相互递归的函数,这些函数通过一组GO
语句手工编译成prog
。如前所述,它可以做三件事:让您拥有本地变量并对其进行初始化;让您拥有标签,如tagbody
中所示,并使用GO
;以及让您使用return
位于名为NIL
的块中:
(defun nr_par (l)
(prog ((l1 l)) ; local binding(s)
ciclu
(if (null l1) (return T)) ; return
(if (null (cdr l1)) (return NIL))
(setf l1 (cddr l1))
(go ciclu))) ; go
(defun nr_par1 (l) ; directly equivalent
(labels ((ciclu (l1)
(if (null l1) (return-from ciclu T))
(if (null (cdr l1)) (return-from ciclu NIL))
(ciclu (cddr l1))))
(ciclu l)))
(defun nr_par2 (l) ; also equivalent
(do ((l1 l (cddr l1)))
(NIL) ; while T ...
(cond
((null l1) (return T))
((null (cdr l1)) (return NIL)))))
函数调用毕竟是一个美化的goto
,不是吗
另请参见一个示例,该示例用一组GO
语句将几个相互递归的函数手工编译成prog
。“不太惯用的lisp”-实际上,60年代和70年代的许多lisp代码都是这样的。今天的示例非常惯用,因为它包含在一种常见的lisp“练习”中(我总是假设要求像“使用PROG、COND、GO、CD[D]R等编写某某函数”。似乎世界上没有一位教师会接受(evenp(length list))
作为解决方案。甚至(reduce#'(lambda(v#)(而不是v))list:初始值t)
“不太惯用的lisp”-实际上这是60年代和70年代许多lisp代码的样子。今天的示例非常惯用,因为它包含在一种常见的lisp“练习”风格中(我总是假设要求类似于“使用PROG、COND、GO、CD[D]R等编写某个函数”。似乎世界上没有一位教师会接受(evenp(length list))
作为解决方案。甚至(reduce#'(lambda(v#)(not v))list:初始值t)