Logix: Lisp with Python syntax

New discovery of the day: Logix. Logix is Python, with macros. Logix is Lisp, with Python syntax. Logix is a programming language that lets you create programming languages. Logix is whatever language you need it to be.

If you’re familiar with Lisp, you already grasp how powerful macros can be. If all you’ve used is Python, let’s take a look at a practical example. Let’s say you’re writing a threaded program, and throughout your code is scattered constructions like:

_lock.acquire()
try:
    print "We have the lock, now doing some work"
finally:
    _lock.release()

Wouldn’t it be nice to have a synchronized construct that would do the work for you? You could write it as a function, but then you’d have to pass in the code you want to run, which means turning it into another function or a lambda, and that just creates more boilerplate. With macros, you’d be able to do something like this:

defmacro synchronized(lock, codeblock):
    lock.acquire()
    try:
        codeblock
    finally:
        lock.release()

Some magic would be required to pass in the codeblock, of course.

Well, in Logix, this is how that macro would be written:

defop 0 "synchronized" "(" $lock:expr ")" ":" $code:block
    macro lock code
        lock.acquire()
        `try:
            *code
        `finally:
            lock.release()

If you’re wondering about the backslashes and backquotes, read the Logix tutorial. It will explain what those do, and in the process introduce you to what Logix is capable of (hint: quite a lot!).

What makes Logix so powerful? The same thing that makes Lisp so powerful: the idea that code is data, and data is code. Which means you can pass around chunks of code to functions, save them in variables, and generally do whatever you want with them. I’ve been meaning to learn Lisp for a while now, but I’ve always been put off by its syntax. That’s because the basic unit of Lisp is the list, and lists inside lists inside lists meant Lots of Irritating Superfluous Parenthesis :-). And I could never get used to writing addition as (+ 1 2 3) instead of 1 + 2 + 3. But Logix is based on Python, and inherits a lot of Python’s syntax. So instead of parens inside parens, you’ve got blocks based on indentation, and colons at the end of lines signalling that a block is about to start. It’s got the same “clean”-feeling syntax that makes Python so easy to read, but it’s also got the power of Lisp: macros, and the ability to pass code objects (of any kind, not just functions) around. I’m looking forward to playing with it and learning it.

UPDATE, 2005-06-06: The code samples I gave above are for Logix 0.4. 0.5 is going to introduce some changes to the underlying structure (in particular, what “chunks of code” are made of is changing), and so the macro syntax may end up looking a little different. If the code above ends up being wrong, I’ll post an update correcting it.

One Comment

  • Tom Locke says:

    Nice write-up. One thing – you don’t need to escape all those quotes in the defop (some kind of wordpress markup mistake maybe?). I had a dig around but couldn’t find an email address on your site. Are you on the Logix mailing list?