我正在尝试将Lisp作为我的新语言,并且我遇到了一些问题,如何让函数的各个部分对传递给它的列表的每个元素起作用.
为了学习如何解决这个问题,我试图编写一个相当基本的除法形式,当列表中的一个元素为0时(但只返回0),它不会呱呱叫
(defun divtest (elements)
(dolist (x elements)
(if (zerop x) 0 () )
(/ elements)))))
Run Code Online (Sandbox Code Playgroud)
我尝试将其运行为:
(divtest '(20 2 5))
Run Code Online (Sandbox Code Playgroud)
产量:
*** - /: (20 2 5) is not a number
Run Code Online (Sandbox Code Playgroud)
故障点似乎根源于这样一个事实:我没有在提取列表中的元素之前将它们传递给函数(在这种情况下,既没有/也没有dolist按预期工作,因为x从未计算为0).如果我是对的,有人可以告诉我如何进行这种"提取"吗?
注意:这个问题与我之前提到过的问题有关,但由于我不清楚之前答案的哪一部分实际上允许它按照预期的具体问题工作,我决定进一步深入了解基础知识
/将一个或多个数字作为参数,但在您的代码中,您将其传递给列表 - 显然这不起作用.这个功能apply是你的朋友 - (apply #'foo a b (list c d e))相当于(foo a b c d e).请注意,apply要使用的函数和最终列表之间的参数是可选的,因此(apply #'/ '(20 2 5))等效于(/ 20 2 5).
此外,您尝试删除零将无法正常工作.dolist正在为参数列表中的每个项目评估它的主体elements,但是你实际上并没有做任何改变内容的事情elements(评估dolists体的结果没有像你期望的那样被重新分配给源元素).
功能remove-if(及其破坏性对应物delete-if)是您正在寻找的.以下显示了如何使用它(它需要许多可选参数,您不必为此目的而担心).
(defun divtest (elements)
(apply #'/ (remove-if #'zerop elements)))
Run Code Online (Sandbox Code Playgroud)
另请注意,如果elements列表的第一个元素为零(假设我理解函数的意图),这将无法正常运行.所以你可能会想要类似的东西
(defun divtest (elements)
(apply #'/ (first elements) (remove-if #'zerop (rest elements))))
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参阅Hyperspec.