3


我是 lisp 的新手,这是我的问题:
我有一个类似的列表

((a ((length 3) (size 5))) (b ((length 5) (size 7))))...

上面的列表只是一个示例。
我想要的是一个find可以像数据库查询一样工作的函数,例如

(find (and (gt length 4) (lt size 8)))

在这种情况下,上述功能应该b适合我。请注意,此函数的条件参数可以扩展为andor or...
我做了一些研究并且知道eval可以以某种方式帮助我解决这个问题,但我不确定它是如何工作的。
有人可以给我一个例子或给我一些提示吗?

谢谢

4

2 回答 2

5

我不会为此使用 eval 。但这样做相对容易。

您有一系列项目:

((a ((length 3) (size 5)))
 (b ((length 5) (size 7))))

您有一个测试描述,如下所示:

(and (> length 4) (< size 8))

现在你想看看是否

(my-equal '(and (> length 4) (< size 8)) '((length 5) (size 7))

是真的。

所以任务是写MY-EQUAL。通常我会把它写成一个递归函数。

但是如果你想用 来做EVAL,它变得相对容易:

你想评估这个表格:

(let ((length 5) (size 7))
  (and (> length 4) (< size 8)))

现在应该很容易编写 MY-EQUAL。

您可以将其用作

(find term sequence :test #'my-equal :key #'second)

请注意,从流中读取的任意代码的评估存在安全风险。

奖金

我们可以用COMPILEEVAL 代替:

(defun lookup (v bindings)
  (let ((result (assoc v bindings)))
    (if result
        (second result)
      (error "variable ~a not known" v))))

(defparameter *query-operators* '(and or > < =))

(defun generate-query-code (q bindings)
  (cond ((numberp q) q)
        ((symbolp q) `(lookup ',q ,bindings))
        ((consp q)
         (destructuring-bind (op . args)
             q
           (if (member op *query-operators*)
               `(,op ,@(mapcar (lambda (arg)
                                 (generate-query-code arg bindings))
                               args))
             (error "Unknown op ~a" op))))))

(defun compile-query (q)
  (compile nil
           (let* ((bindings (gensym "bindings"))
                  (code (generate-query-code q bindings)))
             `(lambda (,bindings)
                ,code))))

(defun find-query (query descriptions)
  (find-if (compile-query query)
           descriptions
           :key #'second))

例子:

CL-USER 39 > (find-query '(and (> length 4) (< size 8))
                         '((a ((length 3) (size 5)))
                           (b ((length 5) (size 7)))))
(B ((LENGTH 5) (SIZE 7)))
于 2012-12-09T06:44:24.847 回答
4

这篇博文看起来与您的问题有关:http: //xach.livejournal.com/131456.html

length(你必须用你的每条记录的和和实际值之间的小映射来扩展它size,所以可以在你的每条记录上调用闭包链)

于 2012-12-09T09:12:12.563 回答