我已经完成了格雷厄姆的第5.8章练习,我的代码是:
(defun max-min (vec &key (start 0) (end (length vec)))
(cond
((eql start (1- end)) (values (elt vec start) (elt vec (1- end))))
((zerop end) (values nil nil))
(t
(multiple-value-bind (x y) (max-min vec :start (1+ start) :end end)
(let* ((maxx x)(minn y))
(values (max maxx (elt vec start)) (min minn (elt vec start))))))))
您无需担心细节,基本上它只是以“值”形式返回给定矢量的最大值和最小值。
我使用上面的递归来解决问题,但是我的老师用我的批评来标记我的功能“差不多完成了”:
“如果一个函数需要开始和结束,那么长度既不需要也不正确。长度可以是> 0但是它是否开始<结束或者不重要。测试结束全部本身并不相关。”
我现在还不是很清楚,我试图摆脱“end”的(长度vec)默认值,但是end的默认值变为nil。
我们有明确的说法,“长度”最多应调用一次
你能给我一些暗示吗?感谢。
答案 0 :(得分:4)
你的lambda列表没问题。问题是基本情况:(zerop end)
应该被修改,以便在(min-max myvec :start 5 :end 3)
调用时也能获得合理的结果。
下一个批评是关于这两行:
(multiple-value-bind (x y) (max-min vec :start (1+ start) :end end)
(let* ((maxx x) (minn y))
;; ...
如果您希望将递归调用的结果命名为maxx
和minn
,为什么不直接将它们命名为?
(multiple-value-bind (maxx minn) (max-min vec :start (1+ start) :end end)
;; ...
顺便说一句,您可以将它们称为max
和min
(变量和函数有单独的命名空间),或max-of-rest
和min-of-rest
(更具描述性) )。
答案 1 :(得分:0)
我不知道您正在使用的某些lisp功能,但它在我看来非常像您的老师不正确。
“如果一个函数需要开始和结束,那么长度既不需要也不正确。长度可以是0,但是它是否开始<结束或者不重要。测试结束本身并不重要。”
我认为length
是end
的默认值,而您 仅测试end
,而不测试length
他的抱怨似乎已得到解决。
也就是说,在该代码中还有其他一些要抱怨的事情。例如,如果您使用end
<来调用max-min会发生什么? start
?它看起来像你会通过递增开始来递减,直到你用完向量,然后你会得到某种异常。