3

I just want to add the capability to handle lisp query into the initial Prolog implementation in OnLisp text. Since this capability is introduced in the following chapater (a new implementation), I just copied from new implementation and made some modification.

Here are the functions/macros I modified/added.

(=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)))

But when I run the code below, it complains a variable is not defined.

(<- (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

I traced =gen-lisp and expand the macro "with-binds" but found nothing interesting.

(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))) ;

Any ideas about this?

By the way, here is the complete code

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

Thanks in advance.

user1461328
  • 742
  • 2
  • 6
  • 13

1 Answers1

4

(eval form) evaluates form in the null lexical environment, which means that ?G3160 and ?G3159 are not bound inside the call. Indeed, symbols are resolved during compilation, and there is no information about lexical bindings anymore at runtime. I mention compilation but even if you ran your code in an interpreter, there would be no lexical-symbol-value function available for you to resolve a binding, given a symbol at runtime.

The good news is that you don't need to wrap the form in an eval in your case. The difficulty is that the with-binds introduces another level of quotation (expr is quoted). Here is how I would write gen-lisp:

(=defun gen-lisp (expr binds)
  `(let ,(mapcar #'(lambda (v) `(,v (fullbind ,v ,binds)))
         (vars-in expr))
     (if ,expr
         (=values binds)
         (fail))))
coredump
  • 37,664
  • 5
  • 43
  • 77
  • you mean even if it is inside a LET block with which variables are bound to something? – user1461328 Oct 30 '15 at 14:54
  • @user1461328 exactly, after all, the form is quoted and contains only symbols: when you call eval, you have to access the value bound to the symbols at runtime, which has no information about the lexical bindings that were into effect during compilation (eval is not special, it works like any other function). – coredump Oct 30 '15 at 14:57
  • the problems is that if not use eval, just ",expr", I just got a quoted list '(<= ?G3160 ?G3159) without being evaluated. Not quite clear about the lexical environment but think I have to find another way. Thanks! – user1461328 Oct 31 '15 at 04:11
  • I am confused when you say "eval is not special, it works like any other function". Then how about "+" function in `(let ((x 1)) (+ x 1))`. If "+" is evaluate in global env, then how symbol "x" is found? Maybe this is already out of the scope of my original question. – user1461328 Nov 01 '15 at 03:15
  • @user1461328 Lexical scope can be resolved before evaluation starts, based on the symbols being used (if your code is interpreted, you can have `eval` call an auxiliary `eval-env` which uses its own environment data-structure, e.g. a assoc. list of bindings, but there is not much magic involved). In `(let((x 1))(+ x 1))`, the compiler probably does constant propagation, but in the general case, a specific place in memory is used to represent the variable designated by `x`, and that place is referenced to in to code emitted in the call to `+`. But note that eval typically takes a quoted form... – coredump Nov 01 '15 at 13:39
  • @user1461328 ... and you don't share bindings between quoted and unquoted forms : for example, `(let((x 1)) '(+ x 1))` is very different from above and looks more like what eval has to interpret. – coredump Nov 01 '15 at 13:40