为什么来自miniKanren的"disj"在Scheme中起作用,而在Racket中不起作用?



我正在为Racket使用minikanren库,但是我想使用"disj"one_answers";conj"操作符。我希望能够更显式地声明我是为了易读而使用disj还是conj,而不是必须通过conde表达式进行解析,特别是当表达式变得更复杂时。我从"the reason 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 ...))]))

对于前两种情况

可以正常工作
> (run* (x) (disj (== 'foo x)))
'(foo)

,但只在使用多个目标时返回第一个结果:

> (run* (x) (disj (== 'foo x) (== 'bar x) (== 'foobar x)))
'(foo)

为什么会这样?

我似乎无法重现那样的行为。

当我克隆TRS/2e repo时,添加两个

#lang racket
(provide (all-defined-out))

trs2-impl.scm的顶部,运行该文件,然后尝试测试程序,我看到预期的结果:

; 
; Welcome to Racket v7.9.0.3 [cs].
; 
trs2-impl.scm> (run* (x) (disj (== 'foo x) (== 'bar x) (== 'foobar x)))
'((foo) (bar) (foobar))

你看到不同的行为吗?如果是这样,那么我们可以更深入地研究。你知道你用的是哪个版本的Racket吗?我认为这无关紧要,但以防万一。

相关内容