PyLisp: The best of both worlds... Lisp *in* Python

William Annis annis at biostat.wisc.edu
Wed May 16 12:12:41 EDT 2001


        Ok, perhaps this isn't the *best* of any world.  :)

        In response to the recent discussion on Lisp here, I thought
I'd make available for perusal a little library of mine, alpha code
though it is.

        I have implemented a small lisp (lisp-1) interpreter in
Python.  I didn't set out to do this, but I ended up with one and I
think it's sort of cute:

        http://www.biostat.wisc.edu/~annis/creations/PyLisp/

        Surprisingly, implementing macros was reasonably
straightforward.  Due to the idiosyncratic way I handle evaluation --
functions and macros both are responsible for deciding when their
arguments are evaluated -- you can meaningfully treat macros as
first-class objects and get away with it, though it is by no means
clear to me yet what it means to map a macro over a list.

        Some examples (after the colon is the result value):

;;; standard list processing
(first '(a b c)) : a           ; or (car '(a b c))
(rest '(a b c)) : (b c)        ; or (cdr '(a b c))
(cons 'a '(b c d)) : (a b c d)
(setq fred '(a b c)) : (a b c)

;;; all logic operations are fuzzy:
(logic 0.5) : (logic 0.5)
(logic 1.0) : *true*
(not (logic 0.0)) : *true*
(not (logic 0.35)) : (logic 0.65)
(and *true* (not *true*)) : *false*
(or *true* (not *true*)) : *true*
(setq *true* (logic .95)) : (logic 0.95)
(and *true* (not *true*)) : (logic 0.05)
(or *true* (not *true*)) : (logic 0.95)
(setq *true* (logic 1.0)) : *true*        ;; the default

;;; lambdas, of course
(lambda (x y) (* x y)) : (lambda (x y) (* x y))
((lambda (x y) (* x y)) 5 2) : 10

;;; let is useful
(let ((x 5) (y 3)) (+ x y)) : 8
(let ((x 5) (y 3) z) (+ x y)) : 8

;;; for macros, you want the back-tick and interpolation:
`a : a
`(a b ,fred) : (a b (a b c))
`(a b , at fred) : (a b a b c)
`(a (b (c (d (e (f , at fred)))))) : (a (b (c (d (e (f a b c))))))

;;; macros
((macro (x) `(+ ,x 5)) 4) : 9
(def incf (macro (x) `(setq ,x (+ ,x 1)))) : (macro (x) (i-quote (setq , x (+ , x 1))))
(setq whee 33) : 33
(incf whee) : 34
(print whee) : 34

;;; Recursion works just fine:
(def foo
  (lambda (x y)
    (if (<= y 0)
        x
        (begin
          (print x y (<= y 0))
          (foo (cons y x) (- y 1))))))

        I actually set out to write a wrapper around the holmes expert
system code which had a syntax that was easier to parse and which
would allow trivial evaluation of small bits of code.  This little
lisp interpreter is the result, though I have yet to hack in the logic
stuff. 

-- 
William Annis - System Administrator - Biomedical Computing Group
annis at biostat.wisc.edu                       PGP ID:1024/FBF64031
Mi parolas Esperanton - La Internacian Lingvon  www.esperanto.org



More information about the Python-list mailing list