Hi Robert,
Thanks for trying out CLPython!
On 5/5/07, Robert Dodier robert.dodier@gmail.com wrote:
I am interested in using CL-Python as a front end for Lisp libraries. To this end, I wonder how to call a Lisp function from withing Python. I know you can enter " (foo bar)" to call a Lisp function, but its return value is not known to Python. I'd like to be able to do something like "x = foo(bar)".
In the repl the last 3 values are bound to variables _, __ and ___ (like *, ** and *** in Lisp). That is true for both Python and Lisp evaluations:
(car '(22))
22
x = _
22
The variables _ etc are both Python variables and Lisp special variables; so I often do the following to inspect a value returned by Python:
x = .... (inspect _)
But there is a problem if the return value is NIL, as a variable bound to NIL is CLPython's (efficient) way to mark it as unbound:
(or nil)
nil
x = _
Error: NameError: Variable '_' is unbound [condition type: NameError]
To make a Lisp function available in CLPython, probably the cleanest (and about the only) way is to create a subpackage of clpython.module and make the function external:
(defpackage :clpython.module.foo (:use #:common-lisp) (:export #:mylen))
(defun clpython.module.foo:mylen (x) (length x))
Then you can do:
import foo
#<package @ #x10cc89e2>
foo.mylen( [1,2,3] )
3
x = foo.mylen( "abc")
3
Couple of questions related to this. How can I reference Lisp variables from Python
Make the variable external, like 'pi in :clpython.module.math
Note that because Lisp packages can use symbols from other Lisp packages, you should easily be able to write a clpython.module.X package that is just a bridge between Python and a regular Lisp package. (Perhaps function cascade-external-symbols in package.lisp is useful here.)
and vice versa?
Reference it like clpython.module.math:pi or do (use-package :clpython.module.math).
Can I use import to load a Lisp file?
Currently not, "import" only works for Python source files and the corresponding fasl files. But it would be nice to have it work for regular Lisp files too, indeed.
After loading the Lisp file, how do functions and variables in it appear in Lisp --- does the Lisp package name come into play?
Currently you can only reference symbols in direct subpackages of :clpython.module, see above.
What about Lisp symbols which contain characters not allowed in Python --- is there a way to escape them?
Python has no escape syntax for that; but you can use getattr:
(defpackage :clpython.module.foo (:use #:common-lisp) (:export #:a-b*5))
(defun clpython.module.foo:a-b*5 () "you found it!")
import foo
#<package @ #x10cca5ea>
getattr( foo, "a-b*5")()
'you found it!'
Can a Lisp function return arbitrary Lisp objects, and if so how are those displayed in Python?
(defun clpython.module.foo:a-b*5 ()
(list (copy-readtable) *standard-input* *random-state*))
getattr( foo, "a-b*5")()
(#<readtable @ #x10d42d4a>, #<terminal-simple-stream @ #x101277ea>, #<random-state @ #x103239c2>)
Thanks a lot to Willem Broekma for inventing and maintaining CL-Python. I think it's a great idea. My immediate interest is to use CL-Python as an interface for the symbolic computation system Maxima which is written in CL.
I only played with Maxima a little bit, and a Python interface could be nice, indeed. Let me know if you need additional functionality from CLPython for this!
- Willem