我是lisp领域的新手...我正在编写一个代码来解决bfs中的8个难题......
我想将访问列表存储在全局列表中,并定期从函数中更改其值...
(defparameter *vlist* nil)
(defun bfs-core(node-list)
(let (cur-node tmp-node-list)
(if (null node-list)
NIL
(progn
; (if (= 1 (length node-list))
(setq cur-node (car node-list))
(setq tmp-node-list (cdr node-list))
(if (goalp cur-node)
cur-node
((setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node))))))
)
)
)
defparameter one是我的全局变量...并且我想用setq更改其值的函数...我还使用了defvar,setf,set和所有可能的组合...... 任何人都可以帮我解决????
答案 0 :(得分:1)
您当然可以从内部函数更改全局变量:
[1]> (defparameter *visited-lists* nil)
*VISITED-LISTS*
[2]> *visited-lists*
NIL
[3]> (defun change-global-value ()
(setf *visited-lists* (append (list 'new-value)
*visited-lists* )))
CHANGE-GLOBAL-VALUE
[4]> *visited-lists*
NIL
[5]> (change-global-value)
(NEW-VALUE)
[6]> *visited-lists*
(NEW-VALUE)
[7]> (change-global-value)
(NEW-VALUE NEW-VALUE)
[8]> *visited-lists*
(NEW-VALUE NEW-VALUE)
但是让我们再看一下你的代码:
(defun bfs-core(node-list)
(let (cur-node tmp-node-list)
(if (null node-list)
NIL
(progn
; (if (= 1 (length node-list))
(setq cur-node (car node-list))
(setq tmp-node-list (cdr node-list))
(if (goalp cur-node)
cur-node
((setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node))))))
)
)
)
首先,让我们在正确的行上得到括号,然后删除注释掉的代码。大多数Lisp程序员不会像ALGOL风格的语言那样关闭他们的大括号:
(defun bfs-core(node-list)
(let (cur-node tmp-node-list)
(if (null node-list)
NIL
(progn
(setq cur-node (car node-list))
(setq tmp-node-list (cdr node-list))
(if (goalp cur-node)
cur-node
((setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node)))))))))
现在,nil
的第一个分支有一个if
。我们可以将其更改为unless
,其中包含内置progn
,因此我们也不需要:
(defun bfs-core(node-list)
(let (cur-node tmp-node-list)
(unless (null node-list) ;;changed this line to an unless, dropped nil, progn
(setq cur-node (car node-list))
(setq tmp-node-list (cdr node-list))
(if (goalp cur-node)
cur-node
((setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node))))))))
我们还使用let
将一些变量设置为nil
,当我们进入unless
时,我们立即将变量设置为我们实际想要工作的值用。让我们切换它,这样我们只有在我们要使用它们时才创建变量:
(defun bfs-core(node-list)
(unless (null node-list) ;;switched this line and the let below
(let ((cur-node (car node-list)) ;;also set the variables inside the let
(tmp-node-list) (cdr node-list))
(if (goalp cur-node)
cur-node
((setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node))))))))
好的,我们已经有了更清晰的代码。耶!
让我们看一下这里的一个电话:
((setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node))))
你的意思是把它作为单个电话,而不是两个吗?这和它之间有区别:
((setq *vlist* (append cur-node *vlist*)))
(bfs-core (append tmp-node-list (expand cur-node)))
你看到了区别吗?第一个是单一陈述;第二个是两个。您可能想要第二个,因为您想要更改*vlist*
,然后拨打bfs-core
。而且,要那,您需要progn
:
(defun bfs-core(node-list)
(unless (null node-list)
(let ((cur-node (car node-list))
(tmp-node-list) (cdr node-list))
(if (goalp cur-node)
cur-node
(progn (setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node))))))))
答案 1 :(得分:1)
这是您的代码(为标准Lisp样式重新格式化):
(defparameter *vlist* nil)
(defun bfs-core (node-list)
(let (cur-node tmp-node-list)
(if (null node-list)
NIL
(progn
; (if (= 1 (length node-list))
(setq cur-node (car node-list))
(setq tmp-node-list (cdr node-list))
(if (goalp cur-node)
cur-node
((setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node)))))))))
您的代码是一个明确的问题。
表单((setq *vlist* ...) (bfs-core ...))
最终成为函数调用。当您有(exp1 exp2 exp3)
这样的表单时,exp1
是一个应用于exp2
和exp3
参数值的函数。您的exp1
是(setq *vlist* ...)
,它不会评估某个功能,当然,您从未想过它。
您的代码的重写版本,至少会删除错位的函数调用,是:
(defparameter *vlist* nil)
(defun bfs-core (node-list)
(let (cur-node tmp-node-list)
(if (null node-list)
NIL
(progn
; (if (= 1 (length node-list))
(setq cur-node (car node-list))
(setq tmp-node-list (cdr node-list))
(if (goalp cur-node)
cur-node
(progn
(setq *vlist* (append cur-node *vlist*))
(bfs-core (append tmp-node-list (expand cur-node)))))))))
答案 2 :(得分:0)
其他答案是针对当前问题的。作为有关如何更改传递给子例程的变量的值的一般答案,可以将变量作为符号传递:
(defun modify (x)
(set x 100))
(setq d 1) => value of d is 1
(modify 'd) => value of d is 100
因此,要使用按值传递和按引用传递的术语并将其应用于lisp:
(userfunction 'x) is pass by reference,
(Userfunction x) is pass by value.