Writing lisp code from Python
Posted May 30, 2016 at 09:26 AM | categories: lisp, python | tags:
Updated May 30, 2016 at 12:38 PM
Some time ago I wrote about converting python data structures to lisp . I have expanded on that idea to writing lisp programs from Python! The newly expanded code that makes this possible can be found at https://github.com/jkitchin/pycse/blob/master/pycse/lisp.py .
Here are the simple data types known to pycse.lisp:
import pycse.lisp import numpy as np print("a string".lisp) a = 5 b = 5.0 print(a.lisp) print(b.lisp) print([1, 2, 3].lisp) print((1, 2, 3).lisp) print({'a': 4}.lisp) print(np.array([1, 2, 3]).lisp) print(np.array([1.0, 2.0, 3.0]).lisp)
"a string" 5 5.0 (1 2 3) (1 2 3) (:a 4) (1 2 3) (1.0 2.0 3.0)
There are also some more complex types.
import pycse.lisp as pl print(pl.Symbol('lambda')) print(pl.Quote('lambda')) print(pl.SharpQuote('lambda')) print(pl.Cons("a", 5)) print(pl.Alist(["a", 2, "b", 5])) print(pl.Vector([1, 2, 3])) print(pl.Backquote([])) print(pl.Comma([1, 2, 3])) print(pl.Splice([1, 2, 3]))
lambda 'lambda #'lambda ("a" . 5) (("a" . 2) ("b" . 5)) [1 2 3] `() ,(1 2 3) ,@(1 2 3)
You can nest these too.
import pycse.lisp as pl print(pl.Quote(pl.Alist(["a", 2, "b", 5]))) print(pl.Backquote([pl.Symbol('+'), pl.Comma(pl.Symbol('b')), 5]))
'(("a" . 2) ("b" . 5)) `(+ ,b 5)
All that means we can use Python code to generate lisp programs. Here is an example where we make two sub-programs, and combine them into an overall program, then add one more subprogram to it. We wrap the results in an emacs-lisp block, then actually run the block!
import pycse.lisp as pl p1 = [pl.Symbol('mapcar'), [pl.Symbol('lambda'), [pl.Symbol('x')], [pl.Symbol('*'), pl.Symbol('x'), pl.Symbol('x')]], pl.Quote([1, 2, 3, 4])] p2 = [pl.Symbol('princ'), "Hello world"] p = [pl.Symbol('list'), p1, p2] p.append([pl.Symbol('+'), 5, 5]) print(p.lisp)
(list (mapcar (lambda (x) (* x x)) '(1 2 3 4)) (princ "Hello world") (+ 5 5))
(1 4 9 16) | Hello world | 10 |
Wow, it worked! Here is another example of setting up a macro and then running it.
import pycse.lisp as pl s = pl.Symbol bq = pl.Backquote c = pl.Comma p1 = [s('defmacro'), s('f'), [s('x')], "A docstring", bq([s('*'), c(s('x')), 5])] p2 = [s('f'), 5] print(p1.lisp) print(p2.lisp)
(defmacro f (x) "A docstring" `(* ,x 5)) (f 5)
25
I am not too sure where this will be super useful, but it is an interesting proof of concept. I haven't tested this much beyond the original post and this one. Let me know if you find issues with it.
Copyright (C) 2016 by John Kitchin. See the License for information about copying.
Org-mode version = 8.2.10