2013-06-21 3 views

ответ

8

and не является функцией, это макрос, поэтому вы не можете передавать его, как функцию.

Причина, по которой and является макросом, заключается в том, чтобы включить поведение короткого замыкания. Вы можете сделать свой собственный без короткого замыкания версии:

(define (my-and . items) 
    (if (null? items) #t 
     (let loop ((test (car items)) 
       (rest (cdr items))) 
     (cond ((null? rest) test) 
       (test (loop (car rest) (cdr rest))) 
       (else #f))))) 

и my-andможет использоваться с apply.

Для сравнения, вот как выглядит макрос (который действительно делает короткое замыкание), как:

(define-syntax and 
    (syntax-rules() 
    ((and) #t) 
    ((and test) test) 
    ((and test rest ...) (if test 
          (and rest ...) 
          #f)))) 
10

Chris Jester-Янга answer прав, но есть еще один момент, который я хотел бы выделить. Стандартным оператором and является макрос, который задерживает оценку его аргументов (по существу, если не точно), превращая (and a b c) в (if a (if b C#f) #f). Это означает, что если a является ложным, b и c не оцениваются.

У нас также есть возможность определения and-function таким образом, что (and-function a b c) оценивает a, b и c, и возвращает истину, если значения все верно. Это означает, что все a, b и c получают оценку. and-function имеет приятное свойство, что вы можете передать его как функцию, потому что это функция.

Там еще один вариант, который, кажется, отсутствует: and-function-delaying-evaluation, который возвращает возврат, если и только если a, b и c все возвращает истину, но не оценивает, например, b и c если a производит ложное. На самом деле это может быть связано с функцией and-funcalling-function, которая требует, чтобы ее аргументы были списком функций. Например:

(define (and-funcalling-function functions) 
    (or (null? functions) 
     (and ((car functions)) 
      (and-funcalling-function (cdr functions))))) 

(and-funcalling-function 
(list (lambda() (even? 2)) 
     (lambda() (odd? 3)))) 
; => #t 

(and-funcalling-function 
(list (lambda() (odd? 2)) 
     (lambda() (even? 3)))) ; (even? 3) does not get evaluated 
; => #f 

Использование макросов и эту идиому, мы действительно можем реализовать что-то со стандартными and семантикой:

(define-syntax standard-and 
    (syntax-rules() 
    ((standard-and form ...) 
    (and-funcalling-function (list (lambda() form) ...))))) 

(macroexpand '(standard-and (odd? 2) (even? 3))) 
; => 
; (and-funcalling-function 
; (list (lambda() (odd? 2)) 
;  (lambda() (even? 3)))) 

урока, чтобы забрать из этого, конечно, является то, что вы можете есть функция and-like, которую вы можете пройти и по-прежнему получать отложенную оценку; вам просто нужно отложить оценку, обернув вещи в функции и давая функции and-like вызывать эти функции для создания значений. (В схеме это может быть возможностью использовать обещания.)

+1

@ ChrisJester-Young Спасибо за редактирование! Я знаю, что я упомянул о переводе, но я никогда не обходился. Сообщение это гораздо больше в соответствии с вопросом сейчас. Благодаря! –