在Scheme中使用 AND 和 apply 函数

发布于 2024-07-09 23:43:30 字数 167 浏览 8 评论 0 原文

为什么以下不起作用?

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

虽然以下效果很好。

(apply + (list 1 3 2))

R5RS和R6RS好像都是这样?

Why doesn't the following work?

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

While the following works just fine.

(apply + (list 1 3 2))

This seems to be the case in both R5RS and R6RS?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

梓梦 2024-07-16 23:43:30

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

and isn't a normal function because it will only evaluate as few arguments as it needs, to know whether the result is true or false. For example, if the first argument is false, then no matter what the other arguments are, the result has to be false so it won't evaluate the other arguments. If and were a normal function, all of its arguments would be evaluated first, so and was made a special keyword which is why it cannot be passed as a variable.

两仪 2024-07-16 23:43:30
(define and-l (lambda x 
    (if (null? x)
        #t
        (if (car x) (apply and-l (cdr x)) #f))))

请注意,这是 lambda 可变参数
应用示例 (and-l #t #t #f)

或者您可以通过应用程序使用它(按照要求)
例如 (apply and-l (list #t #t #f))

两个选项都可以...

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

pleas notice that this is lambda variadic!
apply example (and-l #t #t #f)

or you can use it via apply procedure(as was asked)
for example (apply and-l (list #t #t #f))

both options are ok...

夏雨凉 2024-07-16 23:43:30

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 的函数参数。

and is actually a macro, whose definition is outlined in R5RS chapter 4. The notation "library syntax" on that page really means it is implemented as a macro.

Section 7.3, Derived expression types gives a possible definition of the and macro:

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

Given this defintion, it is not possible to use and as a function argument to apply.

小ぇ时光︴ 2024-07-16 23:43:30

在Scheme方言MIT/GNU Scheme中,您可以使用函数 boolean/and< /code> 而不是 特殊形式

(apply boolean/and (list #t #t #f)) ;Value: #f

另外,根据记录,我在 Guile Scheme 中找不到任何等效的函数过程索引

(其他答案已经解释了为什么特殊形式 and 不起作用,并展示了如果您的方言中还没有这样的函数,如何编写您自己的替换函数。)

In the Scheme dialect MIT/GNU Scheme, you can use the function boolean/and instead of the special form and.

(apply boolean/and (list #t #t #f)) ;Value: #f

Also, for the record, I couldn’t find any equivalent function in Guile Scheme’s procedure index.

(Other answers have already explained why the special form and won’t work, and shown how to write your own replacement function if there isn’t already such a function in your dialect.)

层林尽染 2024-07-16 23:43:30

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

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

您可以这样应用:

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

两个警告是:

  1. 所有args 被评估,违反了 and 的定义,它应该有快捷行为。
  2. 只允许两个参数。

If you REALLY wanted to have a function pointer to a function that does and, and you don't mind behavior different than the "real" and, then this would work:

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

Which you can apply like this:

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

The two caveats are:

  1. All of the args get evaluated, in violation of the definition of and, which should have shortcutting behavior.
  2. Only two arguments are allowed.
夏天碎花小短裙 2024-07-16 23:43:30

我偶然发现了同样的问题,并在 Racket 中找到了一个优雅的解决方案。
由于问题是“and”是一个宏而不是一个函数,以防止对其所有参数进行求值,所以我读了一些有关“lazyracket”的内容,发现“and”是 中的一个函数那种语言。 所以我想出了以下解决方案,我只需将lazy and导入为“lazy-and”:

#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

I've stumbled across the same problem and found an elegant solution in Racket.
Since the problem is that "and" is a macro and not a function in order to prevent the evaluation of all its arguments, I've read a little on "lazy racket" and found that "and" is a function in that language. So I came up with the following solution where I just import the lazy and as "lazy-and":

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

which yields

(#t #t #t) -> #t
清旖 2024-07-16 23:43:30

试试这个:

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

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

try this:

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

then you can use apply to list-and!

如歌彻婉言 2024-07-16 23:43:30

您还可以使用

(define (andApply lBoo)
(如果(不是(汽车 lBoo))#f
(if (= 1(长度 lBoo)) (车 lBoo)
(andApply (cdr lBoo)))))

You could also use

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

魂ガ小子 2024-07-16 23:43:30

我在玩 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)

I also bump into this problem playing with PLT-Scheme 372, I have digged into the behavior of and-syntax, and figure out the follow code which works just as if one would intuitively expect (apply and lst) to return, but I haven't done exaustive test.

(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

I've also figured out another mind-trapping workaround. I call it mind-trapping because at first I don't know how to turn it into a function... Here it is (only a demo of my intuitive idea):

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

But later I asked a question and got the answer here: Is it possible to generate (quote (quote var)) or ''var dynamically? . With this answer one can easily turn the above idea into a function.

(define (my-quote lst)
  (map (lambda (x) `'',x) lst))

(cons 'and (my-quote (list 'a 'b 'c)))
=> '(and ''a ''b ''c)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文