首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >lisp中的布尔函数式

lisp中的布尔函数式
EN

Stack Overflow用户
提问于 2013-03-18 19:31:32
回答 5查看 378关注 0票数 5

我发现自己处于需要将多个谓词组合为一个谓词的情况下。有没有类似于compliment的标准方法来做这件事?

假设有几个简单的谓词(例如is-fruit-pis-red-pgrows-on-trees-p等)。以及必须使用多于一个的谓词从其中过滤出子集的对象的列表。要做到这一点,还有什么比下面的更好的方法:

代码语言:javascript
复制
(remove-if #'is-fruit-p 
           (remove-if #'is-red-p 
                      (remove-if #'grows-on-trees-p list-of-objects)))
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2013-03-18 20:06:22

我不确定盒子里有没有这样的功能。如果您需要组合可以在编译时确定的函数,您可以编写一个宏来执行此操作。如果您必须动态检测谓词函数,您可以编写function来执行此操作,该函数将循环、抛出函数列表并累积结果,直到条件为false。

宏可能如下所示:

代码语言:javascript
复制
(defmacro combine-predicates (combine-func &rest preds)
  (let ((x (gensym)))
    `(lambda (,x) (,combine-func ,@(loop for p in preds 
                      collecting `(funcall ,p ,x))))))

你可以像这样使用它

代码语言:javascript
复制
(remove-if (combine-predicates and 
                               #'is-fruit-p 
                               #'is-red-p 
                               #'grows-on-trees-p) obj-list)
票数 3
EN

Stack Overflow用户

发布于 2013-03-18 21:40:31

你确定一个特殊的语法真的会有帮助吗?考虑以下几点

代码语言:javascript
复制
(lambda (x)
  (and (is-fruit-p x)
       (or (grows-on-tree-p x)
           (is-red-p x))))

现在更一般的是

代码语言:javascript
复制
(lambda (x)
  (and (is-fruit-p x)
       (or (grows-on-tree-p x)
           (eq (color x) 'red))))

代码语言:javascript
复制
(lambda (x)
  (and (is-fruit-p x)
       (or (grows-on-tree-p x)
           (eq (color x) desired-color)))) ; desired-color captured lexical

即使你为谓词建立了一个特殊的语法,你认为增加的语言复杂性值得你得到的僵化吗?例如,您要定义一个谓词#'weights-exactly-five-ounces-p吗?那#'weights-up-to-and-including-six-and-half-ounces-p呢?

如果您开始需要参数谓词并为此使用lambda形式,那么使用组合器将编写比不使用它更多的代码,因为每个参数项都需要(lambda (x) ...)包装器。更重要的是,代码将更难读取(除了必须学习用于谓词组合的特殊新宏之外)。

如果你被传递了谓词,并且你需要将谓词传递给其他人,那么编写和/或合并器可能是有意义的。但不是为了编写您在示例中使用的代码;为此,我将编写

代码语言:javascript
复制
(remove-if (lambda (x) (or (is-fruit-p x)
                           (is-red-p x)
                           (grows-on-trees-p x)))
           list-of-objects)

更少的写作,更少的阅读,没有额外的学习,琐碎的参数化。

例如,假设您想要一个水果列表,其颜色与您拥有的水果相同(在mine中),重量相同或可能更重……

代码语言:javascript
复制
(remove-if-not (lambda (x) (and (is-fruit-p x)
                                (eq (color x) (color mine))
                                (>= (weight x) (weight mine))))
               objects)
票数 5
EN

Stack Overflow用户

发布于 2013-03-19 05:39:52

quicklisp可安装的alexandria库中提供了诸如disjoinconjoin之类的高阶函数。

代码语言:javascript
复制
CL-USER> (ql:quickload "alexandria")
...
CL-USER> (remove-if (alexandria:disjoin #'zerop #'oddp #'minusp)
                    '(0 -1 1 -2 2))
=> (2)
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15475769

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档