球拍宏无法正常工作

时间:2018-03-22 00:44:29

标签: macros lisp racket datalog hygiene

我之前从未使用过Racket的宏系统,原谅我的无知。我正试图在Racket的Datalog系统中动态定义规则,基本上是这样的:

(datalog rules (! (:- c a b)))

如果我把这样的东西直接放到代码中,一切都很好。但是,我想动态生成这些规则。使用常规函数我会做这样的事情:

(datalog rules (! (apply :- conclusion premises)))

但是datalog!:-都是宏,这使得这不可能。

我的解决方案是编写这个宏:

(define-syntax (make-rule stx)
  (syntax-case stx ()
    ((_ premises conclusion)
      #`(datalog rules (! (:- ,conclusion ,@(map (lambda (x) `,x) premises)))))))

然后像这样调用:

(make-rule '(a b) 'c)

然而,当这确实运行时,查询Datalog数据库会在ab都为真时呈现任何内容。

我尝试双引用语法对象,这样我才能看到输出的内容,就是这样:

'(datalog rules (! (:- c a b)))

所以......如果我直接在我的代码中输入它,那么应该 的确是什么工作!这里发生了什么?这是某种卫生的宏观事物吗?我真的不知道。

谢谢!

编辑:这是一个问题的完整可运行示例。

#lang racket

(require datalog)

(define rules (make-theory))

(define-syntax (make-rule stx)
  (syntax-case stx ()
    ((_ premises conclusion)
       #`(datalog rules (! (:- ,conclusion ,@(map (lambda (x) `,x) premises)))))))

(make-rule '(a b) 'c)
(datalog rules (? c)) ;;Does not work.

(datalog rules (! (:- c a b)))
(datalog rules (! a) (! b))
(datalog rules (? c)) ;;Works.

1 个答案:

答案 0 :(得分:1)

好的,我想我能帮到你。这不是一个卫生问题。

#lang racket
(require datalog)

(define rules (make-theory))

(define-syntax (make-rule stx)
  (syntax-case stx ()
    ((_ (ps ...) c)
     #'(datalog rules (! (:- c ps ...))))))

(datalog rules (! a) (! b))
(make-rule (a b) c)
(datalog rules (? c))

问题在于引用/取消引用。在这里,我只修改了模板以接受您提供的表单。我再也没有真正理解数据记录语言,但是它提供了与你所说的相同的输出"工作"在你的例子中。