Using AND with the apply function in Scheme

前端 未结 9 910
被撕碎了的回忆
被撕碎了的回忆 2020-12-03 05:26

Why doesn\'t the following work?

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

While the following works just fine.

(apply + (list 1 3 2))


        
相关标签:
9条回答
  • 2020-12-03 06:15

    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.

    0 讨论(0)
  • 2020-12-03 06:16

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

    0 讨论(0)
  • 2020-12-03 06:16

    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)
    
    0 讨论(0)
提交回复
热议问题