或作为计划中的程序

时间:2017-12-18 22:13:48

标签: functional-programming macros scheme apply variadic-functions

我想将or应用于列表的每个元素,例如: (apply or '(#t #t #f))预期结果#t,但我收到错误:

  

'#'到'apply'的类型错误(kawa.lang.Macro)(预期:过程,序列或其他运算符)

据我所知,or不是一个程序。 是否有可以使用的程序代替or

4 个答案:

答案 0 :(得分:5)

最简单的方法是使用exists *。只要您使用(apply or some-list),就可以使用(exists values some-list)。或者如果您愿意,可以定义一个使用exists来执行此操作的函数:

#!r6rs
(import (rnrs base)
        (rnrs lists))

(define (or* . lst)
  (exists values lst))

values是身份功能,因此(values x)只是x

exists是定义的高阶函数,因此(exists f (list x ...))等同于(or (f x) ...)

例如(exists values (list #t #t #f))相当于(or (values #t) (values #t) (values #f)),与(or #t #t #f)相同。

尝试一下:

> (apply or* '(#t #t #f))
#t
> (apply or* '(#f #f #f))
#f
> (or* #t #t #f)
#t
> (or*)
#f

* exists有时称为ormapany

答案 1 :(得分:4)

SRFI-1 List Library中,everyany基本上是andor,用于列表上的过程。

#!r6rs

(import (rnrs base)
        (only (srfi :1) every any)

(define num1-10 '(1 2 3 4 5 6 7 8 9 10))
(define odd1-9 '(1 3 5 7 9))

(every odd? num1-10) ; ==> #f
(any odd? num1-10)   ; ==> #t
(every odd? odd1-9)  ; ==> #t

对于布尔值列表,该过程只需要返回参数。 values返回它的参数并作为标识:

(define booleans '(#f #t))
(every values booleans) ; ==> #f
(any values booleans)   ; ==> #t

SRFI-1是一个安全的选择,因为它是即将推出的R7RS Red版本的列表库。在许多R5RS和R6RS实现中包含SRFI-1,如果不是,您可以轻松地从SRFI参考实现中添加它。在DrRacket的默认语言DrRacket中,有ormapandmap,您可以选择使用SRFI-1,而不是使用(require srfi/1)导入它们。

答案 2 :(得分:1)

您可以定义自己使用的程序或

(define (orp . ls) 
     (if (null? ls) #f
           (if (< (length ls) 2) (car ls) (or (car ls) (orp (cdr ls))))))

并使用它:

(apply orp '(#t #f #t))

答案 3 :(得分:1)

重点是or(和ifcondand ....)运算符具有lazy evaluation语义。因此(or #t (/ 1 0))不会除以零。因为or不能成为普通的函数。

你可以编写一个lambda来强制进行评估,例如定义你的eager-or可变参数函数,然后应用它。