Почему не работает следующее?
(apply and (list #t #t #f))
В то время как следующее работает очень хорошо.
(apply + (list 1 3 2))
Это похоже на R5RS и R6RS?
Почему не работает следующее?
(apply and (list #t #t #f))
В то время как следующее работает очень хорошо.
(apply + (list 1 3 2))
Это похоже на R5RS и R6RS?
and
не является нормальной функцией, потому что он будет оценивать только несколько аргументов, сколько нужно, чтобы узнать, является ли результат истинным или ложным. Например, если первый аргумент является ложным, то независимо от того, что другие аргументы, результат должен быть ложным, поэтому он не будет оценивать другие аргументы. Если and
была нормальной функцией, все ее аргументы сначала оценивались, поэтому and
было создано специальное ключевое слово, поэтому его нельзя передать как переменную.
(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))
оба параметра в порядке...
and
на самом деле является макросом, определение которого описано в главе 4 R5RS. Обозначение "синтаксис библиотеки" на этой странице на самом деле означает, что он реализован как макрос.
Раздел 7.3, Производные типы выражений дает возможное определение макроса and
:
(define-syntax and
(syntax-rules ()
((and) #t)
((and test) test)
((and test1 test2 ...)
(if test1 (and test2 ...) #f))))
При этом определении невозможно использовать and
как аргумент функции apply
.
На диалекте Scheme Схема MIT/GNU вы можете использовать boolean/and
вместо специальную форму and
.
(apply boolean/and (list #t #t #f)) ;Value: #f
Кроме того, для записи я не смог найти эквивалентную функцию в Guile Scheme индекс.
(Другие ответы уже объяснили, почему специальная форма and
не работает, и показал, как написать свою собственную функцию замены, если на вашем диалекте уже нет такой функции.)
Если вы ДЕЙСТВИТЕЛЬНО хотите иметь указатель на функцию, которая делает и, и вы не против поведения, отличного от "реального", и тогда это будет работать:
(define and-l (lambda (a b) (and a b)))
Что вы можете применить следующим образом:
(apply and-l (list #t #f))
Два оговорки:
Я наткнулся на ту же проблему и нашел элегантное решение в Racket. Поскольку проблема заключается в том, что "и" является макросом, а не функцией, чтобы предотвратить оценку всех его аргументов, я немного читал "ленивую ракетку" и обнаружил, что "и" является функцией на этом языке. Поэтому я придумал следующее решение, в котором я просто импортирую ленивый и "ленивый" и ":
#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
попробуйте следующее:
(define list-and (lambda (args) (and (car args) (list-and (cdr args)))))
то вы можете использовать apply to list-and!
Вы также можете использовать
(define (andApply lBoo)
(if (not (car lBoo)) #f
(if (= 1(length lBoo)) (car lBoo)
(andApply (cdr lBoo)))))
Я также сталкиваюсь с этой проблемой, играя с PLT-Scheme 372, я перекопал в поведение и-синтаксис и выяснил следующий код, который работает так, как если бы интуитивно ожидал возврат (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)