[clpython-devel] calling Lisp from Python and vice versa

Willem Broekema metawilm at gmail.com
Sat May 5 08:30:51 UTC 2007


Hi Robert,

Thanks for trying out CLPython!

On 5/5/07, Robert Dodier <robert.dodier at 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



More information about the Clpython-devel mailing list