Functional programming 在公共Lisp中求值

Functional programming 在公共Lisp中求值,functional-programming,lisp,eval,common-lisp,Functional Programming,Lisp,Eval,Common Lisp,我不熟悉lisp,下面是我的问题: 我有一个类似的清单 ((a ((length 3) (size 5))) (b ((length 5) (size 7))))... 上面的列表只是一个示例。 我想要的是一个函数find,它可以像数据库查询一样工作 (find (and (gt length 4) (lt size 8))) 在这种情况下,上述函数应该为我找到b。请注意,此函数的条件参数可以用和或或展开。。。 我做了一些研究,知道eval可以在某种程度上帮助我,但我不确定它到底是如何工作的


我不熟悉lisp,下面是我的问题:
我有一个类似的清单

((a ((length 3) (size 5))) (b ((length 5) (size 7))))...
上面的列表只是一个示例。
我想要的是一个函数
find
,它可以像数据库查询一样工作

(find (and (gt length 4) (lt size 8)))
在这种情况下,上述函数应该为我找到
b
。请注意,此函数的条件参数可以用
展开。。。

我做了一些研究,知道
eval
可以在某种程度上帮助我,但我不确定它到底是如何工作的。
有人能给我举个例子或给我一些提示吗


谢谢

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

您有一系列项目:

((a ((length 3) (size 5)))
 (b ((length 5) (size 7))))
您有一个测试描述,如下所示:

(and (> length 4) (< size 8))
现在应该很容易写出我的等号了

你可以把它当作

(find term sequence :test #'my-equal :key #'second)
请注意,对从流中读取的任意代码进行评估是一种安全风险

奖金

我们可以使用
COMPILE
而不是EVAL:

(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))
(defun查找(v绑定)
(let((结果(关联v绑定)))
(如有结果)
(第二个结果)
(错误“变量~a未知”v)))
(defparameter*查询运算符*'(和或><=)
(定义生成查询代码(q绑定)
(条件((编号q)q)
((symbolp q)`(lookup',q,bindings))
((消费q)
(解构绑定(op.args)
Q
(如果(成员op*查询运算符*)
`(,op,@(地图车(阿格州)
(生成查询代码参数绑定))
args)
(错误“未知op~a”op()()))
(定义编译查询(q)
(无
(let*((绑定(gensym“绑定”))
(代码(生成查询代码q绑定)))
`(λ(,绑定)
,代码)))
(定义查找查询(查询描述)
(查找if(编译查询)
描述
:键(秒)
例如:

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)))
CL-USER 39>(查找查询“(和(>长度4)(
这篇博文似乎与您的问题有关:

(您必须使用
长度
大小
与每个记录的实际值之间的小映射来展开它,以便可以对每个记录调用闭包链)

(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)))