Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Want to access lexically defined functions using EVAL in CLISP

Tags:

clisp

Why won't this piece of code work?

(setf x '(foo bar (baz)))

(labels 
    ((baz () (print "baz here"))) 
    (baz) ;works
    (eval (third x))) ;fails with the below message

*** - EVAL: undefined function BAZ

I'm using GNU CLISP.

like image 588
Sunder Avatar asked Jun 23 '13 19:06

Sunder


2 Answers

In Common Lisp, eval evaluates its argument in a null lexical environment, so your lexically bound function baz can't be found.

While the Common Lisp standard doesn't provide a portable way to access the lexical environment and invoke eval with it, your implementation might have this functionality. For example, in CLISP:

cs-user> (setf x '(foo bar (baz)))

(foo bar (baz))
cs-user> (labels ((baz () (print "baz here"))) 
           (eval-env (third x) (the-environment)))

"baz here" 
"baz here"
cs-user> 

See geocar's answer for other approaches.

like image 146
danlei Avatar answered Oct 20 '22 16:10

danlei


Because common lisp doesn't have special functions.

Check the description of EVAL:

Evaluates form in the current dynamic environment and the null lexical environment.

Since the lexical environment is empty, your baz function (defined by labels) isn't accessible. You'd think you could fix this by putting baz in the dynamic environment (you might want something like (declare (special baz)) or (declare (special (function baz))) or something like this) but alas: there's no way to do this.

You could simulate it yourself by creating:

(defvar baz* nil)
(defun baz (&rest args) (apply baz* args))

You then need to dynamically set baz* instead of using labels:

(setf x '(foo bar (baz)))
(let ((baz* (lambda () (print "baz here"))))
  (eval (third x)))

The reason why is just some hard bits about optimisation leaking into the spec. Basically, every function-call would need some stubbing unless the compiler could prove that the function would never get defined dynamically swizzleable. That's hard to do efficiently, and it's not something most CL programmers ever did, so the spec-writers simply forbade it.

As you can see, and as with most things in CL, you can easily get it yourself if you need it. However. Given that most CL programmers never do this, you may want to re-examine why you're trying to do things this way.

like image 43
geocar Avatar answered Oct 20 '22 16:10

geocar