私は Racket の minikanren ライブラリを使用していましたが、"disj" および "conj" 演算子を使用したいと考えていました。特に式がより複雑になった場合、conde 式を解析する必要はなく、読みやすさのために disj と conj のどちらを使用しているかをより明示的に宣言できるようにしたいと考えています。「The Reasoned Schemer」からソースをコピーしました。
(define (append∞ s∞ t∞)
(cond
((null? s∞) t∞)
((pair? s∞)
(cons (car s∞)
(append∞ (cdr s∞) t∞)))
(else (λ ()
(append∞ t∞ (s∞))))))
(define (disj2 g1 g2)
(λ (s)
(append∞ (g1 s) (g2 s))))
(define-syntax disj
(syntax-rules ()
[(disj) '()]
[(disj g) g]
[(disj g0 g ...) (disj2 g0 (disj g ...))]))
これは最初の 2 つのケースで適切に機能します
> (run* (x) (disj (== 'foo x)))
'(foo)
ただし、複数のゴールを使用する場合は最初の結果のみを返します。
> (run* (x) (disj (== 'foo x) (== 'bar x) (== 'foobar x)))
'(foo)
どうしてこれなの?