Я попробовал его в Ракетка как этотПочему (применять и «(1 2 3)) не работает, пока (и 1 2 3) работает в R5RS?
> (apply and '(1 2 3))
. and: bad syntax in: and
> (and 1 2 3)
3
Кто-нибудь есть идеи по этому поводу?
Я попробовал его в Ракетка как этотПочему (применять и «(1 2 3)) не работает, пока (и 1 2 3) работает в R5RS?
> (apply and '(1 2 3))
. and: bad syntax in: and
> (and 1 2 3)
3
Кто-нибудь есть идеи по этому поводу?
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))))
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 вызывать эти функции для создания значений. (В схеме это может быть возможностью использовать обещания.)
@ ChrisJester-Young Спасибо за редактирование! Я знаю, что я упомянул о переводе, но я никогда не обходился. Сообщение это гораздо больше в соответствии с вопросом сейчас. Благодаря! –
Потому что 'и' является макросом, а не функцией. –