刚开始学习lisp,我需要编写一个函数,COUNTER,就像标题中提到的那样。例如,
(COUNTER 'fizz '(fizz (buzz (fizz) (buzz fizz)) fizz))
应该返回4
我写了以下内容
(defun COUNTER (atom list)
(cond
((null list) 0)
((equal atom (first list)) (+ 1 (COUNTER atom (rest list))))
(t (COUNTER atom (rest list)))))
仅计算最高级别的原子(在示例的情况下,我的输出为2)。我需要添加什么才能读取嵌套列表?我知道我应该遍历子列表并对结果求和,但我不确定我应该使用哪个谓词以及我应该放在哪里。我正在考虑
((equal atom (first list)) (+ 1 (COUNTER atom (rest list))))
我尝试过以下无效
(defun COUNTER (target nest_list)
(cond ((null nest_list) 0)
(cond (atom (first nest_list) ((equal target (first nest_list)) (+ 1 (COUNTER target (rest nest_list)))))
(t (COUNTER target (first nest_list))))
(t (COUNTER target (rest nest_list)))))
我收到了来自它的编译错误。我的逻辑似乎有道理。我正在测试实体是一个原子还是一个列表,如果是原子,那么看它是否相等并加1,否则重复,如果它是一个列表。我不确定我是否对括号放置做错了,或者我是否允许在这样的cond中使用cond。
答案 0 :(得分:1)
您可以关闭计数器以避免传递太多参数。
此外,您可能应该像CL函数那样传递自定义test
函数。
(defun counter (search tree &key (test #'eql))
(let ((total 0))
(labels
;; Our tree walker. Both counter and search are accessible
;; from the lexical environment, so there is no need to
;; pass them as arguments.
((walk (tree)
(cond
;; First, see if current element matches the search.
;; That allows to search for a list inside a tree.
((funcall test tree search) (incf total))
;; Otherwise, if this is a cons-cell, recurse in CAR and CDR
((consp tree)
(walk (car tree))
(walk (cdr tree))))))
;; Initiate walk
(walk tree)
;; Return total
total)))
如果这是一个家庭作业,我不认为这可以满足您的要求(您可能希望提供纯粹的递归功能)。但是,如果您了解上述内容,那么构建一个永远不会改变变量的递归方法应该不难。
供参考:
LABELS
:本地的,可能是递归的,功能性绑定
COND
:广义,级联如果
LET
:局部变量绑定
&KEY
:lambda列表中的命名参数
INCF
:增加地点
What's the difference between eq, eql, equal, and equalp in Common Lisp?
(counter '(3 2)
'(a b (c d 3) (3 2) e f)
:test #'equalp)
=> 1
(counter 3 '(a b (c d 3) (3 2) e f))
=> 2
答案 1 :(得分:0)
您还需要检查first list
本身是原子还是列表。如果它是一个原子,那么你当前的逻辑是正确的;如果它是一个列表,那么还需要在此列表中重现。
我删除了有关参数名称的评论,因为它在大多数功能齐全的LISP版本中都不是问题。感谢 coredump 进行更正。
(defun COUNTER (target nest_list)
(cond ((null nest_list) 0)
(cond (atom (first nest_list))
(equal target (first nest_list)) (+ 1 (COUNTER target (rest nest_list))))
(t (COUNTER target (rest nest_list)))))
现在,在新 cond 的 else 分支中,插入另一个递归:
(COUNTER (target (first nest_list)))
您需要将此(而不是 1 )添加到(rest nest_list)的计数中。这会让你感动吗?我知道我的结构并不小心,但我试图避免为你做这份工作。