【问题标题】:about the Prolog implementation关于 Prolog 的实现
【发布时间】:2015-10-30 14:05:16
【问题描述】:

我只想将处理 lisp 查询的功能添加到 OnLisp 文本中的初始 Prolog 实现中。 由于该功能在下章(新实现)中介绍,我只是从新实现中复制并进行了一些修改。

这是我修改/添加的函数/宏。

(=defun prove-query (expr binds)
    (case (car expr)
      (and (prove-and (cdr expr) binds))
      (or (prove-or (cdr expr) binds))
      (not (prove-not (cadr expr) binds))
          (lisp (gen-lisp (cadr expr) binds)) ;;; added
      (t (prove-simple expr binds))))

(defmacro with-binds (binds expr)
  `(let ,(mapcar #'(lambda (v) `(,v (fullbind ,v ,binds)))
         (vars-in expr))
     (eval ,expr)))             ;;; copied the whole macro from new implementaion and modified this line.

(=defun gen-lisp (expr binds)  ;;; copied from new implementation but modified
  (if (with-binds binds expr)
       (=values binds)
     (fail)))

但是当我运行下面的代码时,它抱怨没有定义一个变量。

(<- (ordered (?x)))

(<- (ordered (?x ?y . ?ys))
    (lisp (<= ?x ?y))
    (ordered (?y . ?ys)))

(with-inference (ordered (1 3 6))
  (print t))

*** - EVAL: variable ?G3159 has no value
The following restarts are available:
USE-VALUE      :R1      Input a value to be used instead of ?G3159.
STORE-VALUE    :R2      Input a new value for ?G3159.
ABORT          :R3      Abort main loop

我追踪了 =gen-lisp 并展开宏“with-binds”,但没有发现任何有趣的东西。

(macroexpand '(with-binds '((?G3161 6) (?G3160 . 3) (?G3159 . 1)) '(<= ?G3160 ?G3159)))

(LET
 ((?G3160 (FULLBIND ?G3160 '((?G3161 6) (?G3160 . 3) (?G3159 . 1))))
  (?G3159 (FULLBIND ?G3159 '((?G3161 6) (?G3160 . 3) (?G3159 . 1)))))
 (EVAL '(<= ?G3160 ?G3159))) ;

对此有什么想法吗?

顺便说一下,这里是complete code

https://drive.google.com/file/d/0B7t_DLbSmjMNRVh5SDBXdUVheDg/view?usp=sharing

提前致谢。

【问题讨论】:

    标签: lisp common-lisp on-lisp


    【解决方案1】:

    (eval form)null 词法环境 中计算 form,这意味着 ?G3160?G3159 未绑定在调用中。 事实上,符号在编译期间被解析,并且在运行时不再有关于词法绑定的信息。 我提到了编译,但即使你在解释器中运行代码,也没有lexical-symbol-value 函数可用于解析绑定,在运行时给定一个符号。

    好消息是,在您的情况下,您不需要将表单包装在 eval 中。困难在于with-binds 引入了另一个级别的引用(引用expr)。以下是我将如何写gen-lisp

    (=defun gen-lisp (expr binds)
      `(let ,(mapcar #'(lambda (v) `(,v (fullbind ,v ,binds)))
             (vars-in expr))
         (if ,expr
             (=values binds)
             (fail))))
    

    【讨论】:

    • 你的意思是即使它在一个 LET 块内,其中变量绑定到某个东西?
    • @user1461328 确切地说,表单被引用并且只包含符号:当你调用 eval 时,你必须在运行时访问绑定到符号的值,它没有关于词法绑定的信息在编译期间生效(eval 并不特殊,它与任何其他函数一样工作)。
    • 问题是,如果不使用 eval,只使用 ",expr",我只是得到一个引用列表 '(
    • 当你说“eval 并不特殊,它像任何其他函数一样工作”时,我很困惑。那么(let ((x 1)) (+ x 1))中的“+”函数呢?如果在全局环境中计算“+”,那么如何找到符号“x”?也许这已经超出了我原来的问题的范围。
    • @user1461328 词法范围可以在评估开始之前根据使用的符号解析(如果你的代码被解释,你可以让eval调用一个辅助eval-env,它使用它自己的环境数据-结构,例如一个关联的绑定列表,但涉及的魔法并不多)。在(let((x 1))(+ x 1)) 中,编译器可能会进行常量传播,但在一般情况下,内存中的特定位置用于表示x 指定的变量,并且在调用@ 时发出的代码中引用了该位置987654336@。但请注意,eval 通常采用带引号的形式...
    猜你喜欢
    • 2012-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多