我试图写一个(高阶函数),它接受一个向量和一个函数,并根据该函数进行二进制搜索,即,如果它返回-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,但显然您正在处理向量,所以可能是vecvector
 (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更改为另一次调用您可以从本地函数内部引用binsearchbin-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))))

09-11 19:26