以下が機能しないのはなぜですか?
(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
結果が真か偽かを知るために、必要な数の引数のみを評価するため、通常の関数ではありません。たとえば、最初の引数が false の場合、他の引数が何であれ、結果は false でなければならないため、他の引数は評価されません。通常の関数の場合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
は実際にはマクロであり、その定義はR5RS の第 4 章で概説されています。そのページの「ライブラリ構文」という表記は、実際にはマクロとして実装されていることを意味します。
セクション7.3, 導出された式の型and
は、マクロの可能な定義を示します:
(define-syntax and
(syntax-rules ()
((and) #t)
((and test) test)
((and test1 test2 ...)
(if test1 (and test2 ...) #f))))
この定義を考えるとand
、関数の引数としてを使用することはできませんapply
。
私は同じ問題に出くわし、Racket でエレガントな解決策を見つけました。問題は、「and」がすべての引数の評価を防ぐために関数ではなくマクロであることなので、「怠惰なラケット」について少し読んだところ、「and」がその言語の関数であることがわかりました。だから私は、怠け者を「怠け者と」としてインポートするだけの次の解決策を思いつきました:
#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
and を実行する関数への関数ポインターが本当に必要で、「実際の」and とは異なる動作を気にしない場合は、次のようにします。
(define and-l (lambda (a b) (and a b)))
次のように適用できます。
(apply and-l (list #t #f))
注意点は次の2つです。
これを試して:
(define list-and (lambda (args) (and (car args) (list-and (cdr args)))))
次に、apply to list-and! を使用できます。
また、PLT-Scheme 372 で遊んでいるときにこの問題に遭遇しました。and 構文の動作を掘り下げて、直観的に返されることを期待(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
しかし、後で私は質問をして、ここで答えを得ました: Is it possible to generate (quote (quote var)) or ''var dynamic? . この答えがあれば、上記のアイデアを関数に簡単に変えることができます。
(define (my-quote lst)
(map (lambda (x) `'',x) lst))
(cons 'and (my-quote (list 'a 'b 'c)))
=> '(and ''a ''b ''c)