【问题标题】: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)

这是为什么?

【问题讨论】:

    标签: scheme racket logic-programming minikanren


    【解决方案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 实现似乎可以正常工作。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2013-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    • 2023-04-06
    • 2012-11-23
    • 1970-01-01
    相关资源
    最近更新 更多