Подтвердить что ты не робот

Использование AND с функцией apply в схеме

Почему не работает следующее?

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

В то время как следующее работает очень хорошо.

(apply + (list 1 3 2))

Это похоже на R5RS и R6RS?

4b9b3361

Ответ 1

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

Ответ 2

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

оба параметра в порядке...

Ответ 3

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.

Ответ 4

На диалекте Scheme Схема MIT/GNU вы можете использовать boolean/and вместо специальную форму and.

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

Кроме того, для записи я не смог найти эквивалентную функцию в Guile Scheme индекс.

(Другие ответы уже объяснили, почему специальная форма and не работает, и показал, как написать свою собственную функцию замены, если на вашем диалекте уже нет такой функции.)

Ответ 5

Если вы ДЕЙСТВИТЕЛЬНО хотите иметь указатель на функцию, которая делает и, и вы не против поведения, отличного от "реального", и тогда это будет работать:

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

Что вы можете применить следующим образом:

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

Два оговорки:

  • Все аргументы оцениваются в нарушение определения и, которое должно иметь краткое поведение.
  • Разрешены только два аргумента.

Ответ 6

Я наткнулся на ту же проблему и нашел элегантное решение в 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

Ответ 7

попробуйте следующее:

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

то вы можете использовать apply to list-and!

Ответ 8

Вы также можете использовать

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

Ответ 9

Я также сталкиваюсь с этой проблемой, играя с 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)