我目前正在尝试从projecteuler.net解决问题1。对此函数的评估仅返回函数的名称。我究竟做错了什么?
{"id":"123","title":"aaa","url":"aaaa","visit":"1"},{"id":"456","title":"aaa","url":"aaaa","visit":"0"},{"id":"789","title":"aaa","url":"aaaa","visit":"0"},
答案 0 :(得分:4)
评估此功能仅返回功能的名称。
我无法复制这一点,您是如何在哪个环境下测试代码的?
使用SBCL,这是评估defun
表单打印的内容:
; in: DEFUN NSUM
; (N = 0)
;
; caught WARNING:
; undefined variable: =
=
符号用于评估为变量的位置。如果你想调用绑定到=
的函数,即(function =)
,也可以写#'=
,那么你必须写(= ... ...)
。
; caught STYLE-WARNING:
; undefined function: N
由于您在正常评估规则下编写了(N = 0)
,即N
作为表单的第一个元素,因此代码会尝试调用函数N
。在您的情况下,您没有定义此类功能。
; (COND ((MOD N 5) = 0) (NSUM (- N 1) (+ SUM N)) ((MOD N 3) = 0)
; (NSUM (- N 1) (+ SUM N)) (NSUM (- N 1) (+ SUM N)))
; --> IF
; ==>
; (IF NSUM
; (PROGN (- N 1) (+ SUM N))
; (IF (MOD N 3)
; (PROGN = 0)
; (IF NSUM
; (PROGN (- N 1) (+ SUM N))
; (IF NSUM
; (PROGN # #)
; NIL))))
;
; caught WARNING:
; undefined variable: NSUM
您正在编写cond子句,在该上下文中,每个子句应该是一个匹配(test . body)
的列表,即一个test
表达式,后跟case主体(可能为空)。你写道:
(cond ( (mod n 5) = 0) ( nSum ( - n 1) (+ sum n)) ...)
在上面,你有两个子句,一个(试图)测试N
是否可被5整除,另一个测试nSum
是否为真。
; (SUM)
;
; caught STYLE-WARNING:
; undefined function: SUM
您在SUM
周围添加了括号,这意味着您要调用函数SUM
(当前未定义)。括号在Lisp中很重要。
以下是修复之前错误并根据Lisp样式规则对其进行格式化的代码:
(defun nSum (n sum)
(if (= n 0)
sum
(cond
((= 0 (mod n 5)) (nSum (- n 1) (+ sum n)))
((= 0 (mod n 3)) (nSum (- n 1) (+ sum n)))
(t (nSum (- n 1) (+ sum n))))))
您的代码无法计算所需的功能。请阅读Gwang-Jin Kim's answer以了解如何以尾递归的方式计算它,或者在下面找到基于循环的方法。
另外一些评论w.r.t.式:
你不应该在Lisp中使用 snakeCase ,而是使用破折号来分隔单词,谦卑地称为 lisp-case (显然,也是{ {1}})。
您的kebab-case
和if
可以合并在一起。另外,请注意负面cond
。
当两个测试导致执行相同的代码时,您可以执行N
。这可以避免代码重复。
使用LOOP
:
(or test1 test2)
答案 1 :(得分:2)
(defun nsum (n)
(labels ((inner-nsum (m sum) ; using `labels` define local recursive function
(cond ((= m 0) sum)
((= (mod m 3) 0) (inner-nsum (- m 1) (+ m sum)))
((= (mod m 5) 0) (inner-nsum (- m 1) (+ m sum)))
(t (inner-nsum (- m 1) sum)))))
(inner-nsum (- n 1) 0))) ; call it with n decremented by 1
; to implement "below n"
(nsum 10) ;; 23 ; test successful!
(nsum 1000) ;; 233168
答案 2 :(得分:0)