Friday, May 12, 2006


I gave a presentation on the work I've done on Noodle at last night's Utah Python User's Group meeting. I made an alpha release of Noodle available to complement that presentation. You can find both a tarball and the slides (OpenOffice format) at The slides are in PDF format on UPyUG's site here.

The conclusion I made in the presentation was that designing a language is far harder than implementing it. I think Noodle works very well -- that is, there is a decent implementation of the language as designed -- but the design is not good enough. The and [foo bar] attribute reference and subscripting syntaxes I mentioned previously have yet to feel comfortable to me. The semantics of macro namespaces leave some cases which are difficult to handle or just plain annoying. There are more warts than those. Noodle is not yet a language I would use in preference to Python or Lisp for general work.

I do still think it could reach that point, but who knows what could change by then? As I mention on the last slide, I reserve the right to change everything quite completely. This release of Noodle is more for the academic interest of others, rather than being a good tool for real work.

Next step is to put up some prettified docs and a tutorial.


brant said...

I have to say that I think this project is going in the wrong direction. Python and Lisp have very divergent philosophies from the onset as far as syntax goes. Lisp syntax sucks. It sucks like crazy, I'm sorry. What Lisp excels at is the elegance of offering everything as a list/tuple, rather than as an imperative command. I think, perhaps, you should rethink that idea into Python and see what you can come up with. For instance, let's just for a minute decide that a tuple with an @ in front evaluates as a function in Python:
@(foo, bar, baz)

Now see where that goes.

paul cannon said...


I'm not sure I catch your drift. If @(foo, bar, baz) would be an acceptable syntax to you, what exactly is it about Lisp syntax that you don't like?

There's rather a lot about Lisp syntax I like, myself (hence the project).

Noodle does offer everything as a list/tuple, rather than as imperative commands.

brant said...

Man, while re-reading my post, it seems so arrogant. I really don't mean it that way. I just mean I'd rather see the awesomeness of Lisp placed into Python rather than sitting beside it. What I don't like about Lisp is the unreadability of the practical, nitty-gritty functions that you are forced to do functionally. So if you could express some things functionally in Python, I think that would be far simpler.

brant said...

Oh one other thing: Maybe what we really need in Python is a way to do controlled domain specific languages (like Lisp macros). With a really kickass system for that, you could make one that matched Lisp.

Anonymous said...

Interesting work, Paul.

One thing that looked a bit confusing is the assignment operator (= var value) -- if you are used to the operator with the same syntax, but different meaning, in Lisp.

Wouldn't `set!' or `setq' look clearer?

paul cannon said...


Could you come up with some specific examples of the nitty-gritty unreadable functions? I would like to go as far as I can in avoiding that sort of thing.

Also, I'd be interested in hearing more about the ideal that you're picturing. I mean, surely one can "express some things functionally in Python" right now. If what you're looking for is Python syntax with macros on top, does Logix fit, or is there some particular area where that doesn't cut it?

paul cannon said...

And about = vs. set/set!:

I did have 'set' as the assignment operator initially, along with '=' as an equality test. It was ok, but once I tried using the Python operators, they grew on me very quickly. It felt right, and I knew I had a winner.

Naturally I had to diverge from Python syntax a lot to incorporate S-expressions into Noodle, but I have tried to maintain as much of Python syntax as I still could.

Zhyla said...

I've been thinking of something along these lines for a while, glad someone actually put together an implementation. Not sure about some of the syntax choices. Why keep the [0, 1, 2] instead of (list 0, 1, 2)? Aside from the name conflict with the existing lisp keyword of course.

paul cannon said...


The more important conflict is with the Python builtin "list", which works in a different way: it expects a single iterable as an argument, if one is given.

The noodle \[1 2 3] syntax is syntactic sugar for (mklist 1 2 3); mklist is a noodle special operator.

As in lisp, you're never required to use any of the syntactic sugar in the reader.

Anonymous said...

Hello Paul,

Regarding to the assignment operator (= vs setq/set!).

An example of a confusing situation is

(define (oops a)
(if (= a None)

`oops' would always return None, differently from what I'd expect (considering I'm used to the `=' behavior in Lisp).

It could lead to the same style of bugs one can find in C code when people mix up the `=' and `==' operators.

Peaker said...

Separation between statements and expressions.

There is a purpose for that separation: "Flat is better than nested". More specifically, Python emphasizes side-effects by making them statements, and thus disallows embedding(hiding?) them inside expressions.

If you want a side-effect, dedicate a whole line for it! It also forces you to be more flat and less nested, which is a generally guiding principle in Python.

paul cannon said...


Yep, there are good reasons for Python's separation of statements and expressions. It doesn't seem like the avoidance of side effects is one of them, though; there are _plenty_ of expressions which have side effects, and not all statements do.

Flat is probably better than nested most of the time, but there are times when the shape of my problem fits a nested program. I'd prefer a language to encourage good practices rather than enforce them. Not to say that Noodle has necessarily accomplished that any better than Python, but it suggests to me that it's possible that removing the distinction is a good thing.

I'll be experimenting with it.

Paddy3118 said...

Saw your example on closures and Python which prompted me to investigate further for fun:


- Paddy.

Scott said...

I was thinking about putting a Lisp syntax on top of Python myself, and I stumbled across your site. Your implementation looks interesting, but I think we came to different conclusions on the flavor of it.

For instance, since operators are never going to be valid Python identifiers, it's tempting to keep them as infix and have the S-expression parser sort it out with a simple recursive descent grammar:

(a + b + [1, 2, 3])

turns into:

($add a ($add b ($list 1 2 3)))

where $add and $list are builtin functions of the Lisp environment. Similarly:

(1, 2, 3) => ($tuple 1 2 3)
(obj.attr) => ($getattr obj 'attr)

Or something like that... Since the translation is fairly obvious for all of the expression operators, you could still have macros on top of it and "code is data is code" still applies.

As another poster noticed, it falls apart a little bit with assignment since that is a statement in Python. Can't really use one = for both. My first thought would be to introduce a := operator that turns into $assign or something like that.

Lisp wants macros, but I think it would be more in the spirit of Python to have macros really be functions that don't evaluate their arguments. Lambda-izing so to speak. This way you could have run-time, not just compile-time, macros. So:

# Define a "macro"
(macro (foo a b)
(body of foo goes here))

# Call the macro
(foo a b)

# But it really gets treated like:
(foo (lambda () a) (lambda () b))

That changes the evaluator a bit. Basically all functions calls would get passed the closures, and only "normal" functions would evaluate and memoize them by default.

Anyway, I'm mostly just rambling, but I figured I'd pop in and say that I like your idea.


cialis said...

Hi, well be sensible, well-all described