在Scheme中使用AND与apply函数

问题描述 投票:0回答:9

为什么以下不起作用?

(apply and (list #t #t #f))

虽然以下方法效果很好。

(apply + (list 1 3 2))

R5RS和R6RS似乎都是这样?

scheme
9个回答
14
投票

and
不是一个普通函数,因为它只会计算所需的尽可能少的参数,以了解结果是真还是假。例如,如果第一个参数为 false,则无论其他参数是什么,结果都必须为 false,因此它不会评估其他参数。如果
and
是普通函数,则将首先评估其所有参数,因此
and
被设为特殊关键字,这就是它不能作为变量传递的原因。


6
投票
(define and-l (lambda x 
    (if (null? x)
        #t
        (if (car x) (apply and-l (cdr x)) #f))))

请注意,这是 lambda variadic! 应用示例

(and-l #t #t #f)

或者您可以通过申请程序使用它(按照要求) 例如

(apply and-l (list #t #t #f))

两个选项都可以...


5
投票

and
实际上是一个宏,其定义在R5RS第4章中有概述。该页面上的“库语法”符号实际上意味着它是作为宏实现的。

7.3 节,派生表达式类型 给出了 and

 宏的可能定义:

(define-syntax and (syntax-rules () ((and) #t) ((and test) test) ((and test1 test2 ...) (if test1 (and test2 ...) #f))))

鉴于此定义,不可能使用

and

 作为 
apply
 的函数参数。


3
投票
在Scheme方言

MIT/GNUScheme中,您可以使用函数boolean/and

代替特殊形式and

(apply boolean/and (list #t #t #f)) ;Value: #f
此外,郑重声明,我在 

Guile Scheme过程索引中找不到任何等效函数。

(其他答案已经解释了为什么特殊形式

and

不起作用,并展示了如果您的方言中还没有这样的函数,如何编写自己的替换函数。)


1
投票
如果你真的想要一个函数指针指向一个执行 and 的函数,并且你不介意与“真实”and 不同的行为,那么这会起作用:

(define and-l (lambda (a b) (and a b)))

您可以这样申请:

(apply and-l (list #t #f))

两个注意事项是:

    所有参数都会被评估,这违反了 and 的定义,它应该具有快捷行为。
  1. 仅允许两个参数。

1
投票
我偶然发现了同样的问题,并在 Racket 中找到了一个优雅的解决方案。 由于问题是“and”是一个宏而不是一个函数,以防止对其所有参数进行求值,所以我读了一些有关“lazyracket”的内容,发现“and”是

that中的一个函数语言。所以我想出了以下解决方案,我只需将惰性和导入为“惰性与”:

#lang racket (require (only-in lazy [and lazy-and])) (define (mm) (map number? '(1 2 3))) (printf "~a -> ~a\n" (mm) (apply lazy-and (mm)))

产生

(#t #t #t) -> #t
    

0
投票
试试这个:

(define list-and (lambda (args) (and (car args) (list-and (cdr args)))))

然后你可以使用 apply to list-and!


0
投票
您也可以使用

(define (andApply lBoo) (if (not (car lBoo)) #f (if (= 1(length lBoo)) (car lBoo) (andApply (cdr lBoo)))))


    


-1
投票
我在玩 PLT-Scheme 372 时也遇到了这个问题,我深入研究了 and 语法的行为,并找出了下面的代码,它的工作原理就像人们直观地期望

(apply and lst)

 返回一样,但我还没有'没有进行详尽的测试。

(define (list-and lst) (cond ((null? lst) '()) ((not (pair? lst)) (and lst)) ((eq? (length lst) 1) (car lst)) (else (and (car lst) (list-and (cdr lst)))) ) ) Welcome to DrScheme, version 372 [3m]. Language: Textual (MzScheme, includes R5RS). > (eq? (and '()) (list-and '())) #t > (eq? (and '#f) (list-and (list '#f))) #t > (eq? (and 'a) (list-and (list 'a))) #t > (eq? (and 'a 'b) (list-and (list 'a 'b))) #t > (eq? (and 'a 'b '()) (list-and (list 'a 'b '()))) #t > (eq? (and 'a 'b '#t) (list-and (list 'a 'b '#t))) #t > (eq? (and 'a 'b '#f) (list-and (list 'a 'b '#f))) #t

我还想出了另一个“思维陷阱”解决方法。我称它为

思维陷阱,因为一开始我不知道如何将它变成一个函数......这就是(只是我直观想法的演示): Welcome to DrScheme, version 372 [3m]. Language: Textual (MzScheme, includes R5RS). > (eval (cons 'and (list ''#f ''#f ''#t))) #f > (eval (cons 'and (list ''a ''b ''c))) c

但后来我问了一个问题并在这里得到了答案:
是否可以动态生成 (quote (quote var)) 或 ''var?
。有了这个答案,我们就可以轻松地将上述想法转化为函数。

(define (my-quote lst) (map (lambda (x) `'',x) lst)) (cons 'and (my-quote (list 'a 'b 'c))) => '(and ''a ''b ''c)


© www.soinside.com 2019 - 2024. All rights reserved.