所以我对lisp很新,而不是程序员先进.刚开始真的.
我正在努力从头开始尝试获得一个非常简单的遗传算法,虽然我的大多数代码似乎都按照需要执行,但我仍然遇到这样一个简单的错误/误解,我被阻止从底部...尽管我在网上试图寻找解决方案,但显然我没有得到一些东西.
基本上,我知道它与我试图调用变量的事实有关,就好像它是一个运算符(变量保存),因此它告诉我我的函数(实际上只是一个持有运算符的变量)是没有定义的.
我的代码的开始工作正常.
(defvar *nb* 8)
(defvar *random-operators* '(+ - * /))
(defun get-operator ()
"Returns an element of the list of operators chosen at random."
(nth (random (length *random-operators*)) *random-operators*))
Run Code Online (Sandbox Code Playgroud)
那么(get-operator)
根据需要让我成为四个随机运算符之一.
我使用这个更简单的代码来测试我的代码的结构,它可以按照需要工作.
(defun ga-simple ()
"Returns the value of genome once it matches *nb* and prints
the number of generations required."
(do ((genome (random 10) (random 10))
(generation-counter 1 (incf generation-counter)))
((eql genome *nb*)
(format t
"The solution is ~S, and it took ~D generations"
genome
generation-counter))))
Run Code Online (Sandbox Code Playgroud)
当我尝试创建一个由三个变量组成的基因组时,问题出现了,一个变量控制着运算符,另外两个变量是整数.
(defun ga-with-operator ()
(do ((genome 42 (opr1 int1 int2))
(generation-counter 0 (incf generation-counter))
(opr1 + (get-operator)
(int1 (random 10) (random 10))
(int2 (random 10) (random 10))
((eql genome *nb*)
(format t
"The solution is ~S, and it took ~D generations"
genome
generation-counter))))
Run Code Online (Sandbox Code Playgroud)
我的编译器警告告诉我问题出在哪里......
;Compiler warnings for "./ga-one.lisp" :
; In GA-WITH-OPERATOR: Unused lexical variable OPR1
;Compiler warnings for "./ga-one.lisp" :
; In GA-WITH-OPERATOR: Undefined function OPR1/
Run Code Online (Sandbox Code Playgroud)
因此,对函数的调用显然(ga-with-operator)
说opr1是一个未定义的函数调用.因此,当"do"宏检查变量基因组的增量条件时,我收集的内容,它会读取列表,期望opr1成为操作符而不是持有操作符的变量......现在,操作员只需输入完美的工作,但我不知道如何使lisp使用opr1的评估值,这是一个运算符,作为整数的运算符...
为了简化,我做了一个函数试图使用我的get-operator函数构建一个单一的基因组,并且即使在那里也很难
(defun get-genome ()
(let ((operator1 (get-operator)))
(operator1 (random 10) (random 10))))
Run Code Online (Sandbox Code Playgroud)
所以我做了一个test-let函数来确保我的"let"变量赋值是正确的...
(defun test-let ()
(let ((rand (get-operator)))
(print rand)))
Run Code Online (Sandbox Code Playgroud)
它确实如此......所以现在我变得绝望,并且遗漏了一些显然非常简单而又至关重要的东西,这些东西都可以粘在一起.
如果有人可以向我解释,或者只是告诉我,如何让简单的(get-genome)
功能工作,我会非常感激.我知道lisp期望一个操作符作为列表中的第一个元素,我的错误源于我给它一个变量而不是运算符...我如何说服它我的变量是它所持有的运算符?
万一有人想知道工作代码......
(defvar *nb* 42)
(defvar *random-operators* '(+ - * /))
(defun get-operator ()
"Return an element of the list of operators chosen at random."
(nth (random (length *random-operators*)) *random-operators*))
(defun get-genome ()
(let ((operator1 (get-operator)))
(funcall operator1 (+ 1 (random 9)) (+ 1 (random 9)))))
(defun ga-with-operator ()
(do ((genome (get-genome) (get-genome))
(generation-counter 0 (1+ generation-counter)))
((eql genome *nb*)
(format t "The solution is ~S, and it took ~D generations"
genome generation-counter))))
Run Code Online (Sandbox Code Playgroud)
在Common Lisp中,FUNCALL
如果函数返回函数或函数存储在变量中,则需要使用它.
(defun get-genome ()
(let ((operator1 (get-operator)))
(funcall operator1 (random 10) (random 10))))
Run Code Online (Sandbox Code Playgroud)
Common Lisp具有不同的函数和值的名称空间.因此,名称既可以是变量,也可以是函数:
(defun foo (list)
(list list list))
Run Code Online (Sandbox Code Playgroud)
list
最后一行中的第一行调用调用的全局函数list
,第二行和第三行实际上是局部变量list
.
(defun ga-with-operator ()
(do ((genome 42 (opr1 int1 int2))
(generation-counter 0 (incf generation-counter))
(opr1 + (get-operator)
(int1 (random 10) (random 10))
(int2 (random 10) (random 10))
((eql genome *nb*)
(format t
"The solution is ~S, and it took ~D generations"
genome
generation-counter))))
Run Code Online (Sandbox Code Playgroud)
以上功能有更多问题.
+
不是一个功能.它是代码中的变量.要使它成为一个函数,你需要引用或函数引用它.'+
或#'+
.INCF
了generation-counter
.加入1
就好了.该DO
循环更新变量.使用(1+ generation-counter)
.