Использование AND с функцией apply в схеме - PullRequest
13 голосов
/ 23 декабря 2008

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

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

Хотя следующее работает просто отлично.

(apply + (list 1 3 2))

Похоже, это относится и к R5RS, и к R6RS?

Ответы [ 9 ]

11 голосов
/ 23 декабря 2008

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

6 голосов
/ 18 июля 2011
(define and-l (lambda x 
    (if (null? x)
        #t
        (if (car x) (apply and-l (cdr x)) #f))))

пожалуйста, обратите внимание, что это лямбда вариад ! применить пример (and-l #t #t #f)

или вы можете использовать его через процедуру подачи заявки (как было предложено) например (apply and-l (list #t #t #f))

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

4 голосов
/ 23 декабря 2008

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.

2 голосов
/ 24 января 2013

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

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

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

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

1 голос
/ 09 мая 2012

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

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

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

Который вы можете применять так:

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

Два предостережения:

  1. Все аргументы оцениваются в нарушение определения и, которые должны иметь ярлык.
  2. Допустимы только два аргумента.
0 голосов
/ 14 июня 2014

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

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

0 голосов
/ 26 декабря 2013

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

попробуйте это:

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

тогда вы можете использовать применить к списку и!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...