常见的lisp如何让我的变量作为它在列表中的第一个时所拥有的运算符?

pro*_*oga 1 common-lisp

所以我对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)

Rai*_*wig 5

在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)

以上功能有更多问题.

  • 你能看到第一个吗?提示:尝试正确缩进.括号是否正确?
  • 还:+不是一个功能.它是代码中的变量.要使它成为一个函数,你需要引用或函数引用它.'+#'+.
  • 你也不需要INCFgeneration-counter.加入1就好了.该DO循环更新变量.使用(1+ generation-counter).