为啥 miniKanren 中的“disj”在 Scheme 中有效,而在 Racket 中无效?
Posted
技术标签:
【中文标题】为啥 miniKanren 中的“disj”在 Scheme 中有效,而在 Racket 中无效?【英文标题】:Why does "disj" from miniKanren work in Scheme but not in Racket?为什么 miniKanren 中的“disj”在 Scheme 中有效,而在 Racket 中无效? 【发布时间】:2021-06-03 09:25:01 【问题描述】:我正在使用 Racket 的 minikanren 库,但想使用“disj”和“conj”运算符。为了清晰起见,我希望能够更明确地声明我是使用 disj 还是 conj,而不是必须通过 conde 表达式进行解析,尤其是当表达式变得更加复杂时。我从“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 ...))]))
这适用于前两种情况
> (run* (x) (disj (== 'foo x)))
'(foo)
但在使用多个目标时只返回第一个结果:
> (run* (x) (disj (== 'foo x) (== 'bar x) (== 'foobar x)))
'(foo)
这是为什么?
【问题讨论】:
【参考方案1】:哼哼。我似乎无法重现这种行为。
当我克隆 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 minikanren 库的混合体,并结合了标准库之上的 disj 函数所需的功能......使用 minikanren 的整个 trs2 实现似乎可以正常工作。谢谢!以上是关于为啥 miniKanren 中的“disj”在 Scheme 中有效,而在 Racket 中无效?的主要内容,如果未能解决你的问题,请参考以下文章