我正在从事遗传编程爱好项目。
我有一个函数/宏设置,当以setq / setf形式计算时,会生成一个类似于此的列表。
(setq trees (make-trees 2))
==> (+ x (abs x))
然后通过战略性使用函数/宏将它绑定到lambda函数#<FUNCTION :LAMBDA (X) ... >
但是,我想比手动分配变量更有效,所以我写了这样的东西:
(setq sample
(let* ((trees (make-trees 2))
(tree-bindings (bind-trees trees))
(evaluated-trees (eval-fitness tree-bindings))))
(list (trees tree-bindings evaluated-trees)))
但是,当我将其放在let表单中时,我会得到EVAL: trees has no value
。我怀疑与SETF相比,宏扩展在LET中没有完全执行,但这对我来说没有意义。
这个问题的原因是什么?
---编辑:猛拉我的代码并将整个文件放入pastebin ---
假设我决定setq不会为我做这个并且我写了一个简单的函数来执行它:
(defun generate-sample()
(让((twiggs(make-trees 2)))
(让((树绑定(bind-trees twiggs)))
(let((evaluate-trees(eval-fitness tree-bindings)))
(列出twiggs树绑定评估树)))))
这会导致...帮助文件错误消息(??!?)...和“eval:variable twiggs没有值”爆炸,这源于SLIME检查中的绑定树定义。
我有理由相信我已经完全收回了我的宏。 http://pastebin.org/673619
答案 0 :(得分:3)
(Setq make-trees 2)
将变量make-trees
的值设置为2,然后返回2.
我没有看到你描述的宏的原因。您的make-trees
是否创建了一个可以解释为程序的随机树,这是真的吗?只需将其定义为defun
的函数即可。我在考虑这样的事情:
(defun make-tree (node-number)
(if (= node-number 1)
(make-leaf)
(cons (get-random-operator)
(mapcar #'make-tree
(random-partition (- node-number 1))))))
Let
和setq
完全不同。 Setq
为现有变量赋值,而let
创建一个带有多个词法绑定的新词法范围。
我认为您应该提供更多代码;目前,你的问题没有多大意义。
更新
我会修复你的片段缩进以使事情更清楚:
(setq sample
(let* ((trees (make-trees 2))
(tree-bindings (bind-trees trees))
(evaluated-trees (eval-fitness tree-bindings))))
(list (trees tree-bindings evaluated-trees)))
现在,如前所述,let*
建立了词汇绑定。这些
仅在其范围内:
(setq sample
(let* ((trees (make-trees 2))
(tree-bindings (bind-trees trees))
(evaluated-trees (eval-fitness tree-bindings)))
;; here trees, tree-bindings, and evaluated-trees are bound
) ; end of let* body
;; here trees, tree-bindings, and evaluated trees are not in scope anymore
(list (trees tree-bindings evaluated-trees)))
最后一行也是虚假的。如果这些名字受到约束,那就会
返回一个元素的列表,这将是评估的结果
功能trees
,tree-bindings
和evaluated-trees
为
参数。
你可能会得到你想要的东西:
(setq sample
(let* ((trees (make-trees 2))
(tree-bindings (bind-trees trees))
(evaluated-trees (eval-fitness tree-bindings)))
(list trees tree-bindings evaluated-trees)))
另一次更新:
宏的目的是在功能无法消除时消除重复的代码。一个常见的应用是处理场所时,你还需要它们来定义新的控制结构。只要您没有看到某些内容无法正常工作,请不要使用宏。
以下是一些可能对您有所帮助的代码:
(defun make-tree-lambda (depth)
(list 'lambda '(x)
(new-tree depth)))
(defun make-tree-function (lambda-tree)
(eval lambda-tree))
(defun eval-fitness (lambda-form-list input-output-list)
"Determines how well the lambda forms approach the wanted function
by comparing their output with the wanted output in the supplied test
cases. Returns a list of mean quadratic error sums."
(mapcar (lambda (lambda-form)
(let* ((actual-results (mapcar (make-tree-function lambda-form)
(mapcar #'first input-output-list)))
(differences (mapcar #'-
actual-results
(mapcar #'second input-output-list)))
(squared-differences (mapcar #'square
differences)))
(/ (reduce #'+ squared-differences)
(length squared-differences))))
lambda-form-list))
(defun tree-fitness (tree-list input-output-list)
"Creates a list of lists, each inner list is (tree fitness). Input
is a list of trees, and a list of test cases."
(mapcar (lambda (tree fitness)
(list tree fitness))
tree-list
(eval-fitness (mapcar #'make-tree-lambda tree-list)
input-output-list)))