我试图写一个(高阶函数),它接受一个向量和一个函数,并根据该函数进行二进制搜索,即,如果它返回-1,我们需要走低,对于1——更高,对于0,我们找到了正确的位置。
我想出了这样的办法,但似乎我在将函数作为参数传递时做错了:
(defun bin-search (ls fpred)
(let ((l (length ls))
(x (aref ls (floor (length ls) 2))))
(labels (binsearch (ls fpred l m)
(case (funcall #'fpred (aref ls m))
(-1 (binsearch (ls fpred l (floor (- m l) 2))))
(0 (return-from binsearch m))
(1 (binsearch (ls fpred m (+ m (floor (- m l) 2)))))))
(binsearch ls fpred 0 l))))
编译器说变量FPRED已定义但从未使用过怎么了?
最佳答案
(defun bin-search (ls fpred)
请使用有意义的名字,你有许多简短的名字或缩写,这是很难阅读的例如,
ls
让我想到一个列表,可以简单地命名为list
,但显然您正在处理向量,所以可能是vec
或vector
? (let ((l (length ls))
(x (aref ls (floor (length ls) 2))))
如果要重用同一let中定义的长度
l
,可以改用let*
,并编写l
,而不是第二次出现(length ls)
。 (labels (binsearch (ls fpred l m)
标签的语法是绑定列表,因此需要添加另一对括号,如
(name (<args>) <body>)
另外,您不需要将
(labels ((binsearch (<args>) <body>)) ...
作为参数传递,它不会从一次调用fpred
更改为另一次调用您可以从本地函数内部引用binsearch
的bin-search
参数。 (case (funcall #'fpred (aref ls m))
当您编写相当于
fpred
的#'fpred
时,您将在函数命名空间中查找(function fpred)
。在这里,您想要访问与名为fpred
的变量相关联的函数,这样您就可以删除fpred
部分。 (-1 (binsearch (ls fpred l (floor (- m l) 2))))
当您编写
#'
时,这意味着:使用一个值调用(binsearch (ls fpred ...))
,通过使用参数调用函数binsearch
括号是重要的,您需要在这里删除它们。 (0 (return-from binsearch m))
(1 (binsearch (ls fpred m (+ m (floor (- m l) 2)))))))
(binsearch ls fpred 0 l))))