Sunday, February 08, 2009

Learning LISP

I'm halfway reading Practical Common Lisp and I'm now beginning to understand a few points about LISP that were not that clear. First of all what are those famous macros and why they're so powerful. I always had the gut feeling that C++ template machinery was not good, it is a different language with a lot of limitations and even doing things like loops or ifs is not impossible but very very hard; not only template debugging is difficult but even reports about syntax errors are so bad that they look like a joke.
LISP macros can do the same as C++ templates (and more), however the language is LISP itself (if, loops, opening files... you can do whatever you need to do "compile time").
I am experimenting with a macro "defentity" that given for example


(defentity simple-point point
(coords point))

(defentity circle line
(center point)
(radius float))


defines two classes, the classes "simple-point" and "circle". The center of a circle entity is a reference to a point entity and this generates a dipendence. When I change the coordinates of a point I want that all the geometry of dependent entities (for example circles that are referencing that point as center) to be invalidated.

I'm still working on it but I already got something working. The defined classes are regular CLOS classes with added "dirty" fields for invalidated geometry, cached results and accessors that do the required recursive "touching" of dependent entities on write operations. Changing referred entities, destruction and link removal is implemented (so when destroying a point all entities depending on it will be notified and given the possibility to remove the link instead of being also destroyed).

Making the same using templates with C++ would be IMO just impossible. Making the same with python would be easy (we did) but keeping much of the logic at runtime. Moving it at compile time with python would be possible but IMO a lot harder (and without much gain indeed).
With C++ a reasonable solution would be using a code generator (written e.g. in PERL) that generates the C++ code needed.

I'm trying the LISP way and so far looks promising...

Python dropped the clear distinction of compile-time and run-time as class and function definition are indeed executable statements; LISP moved further by dropping also the parse-time separation because thanks to macros even the parsing of the source is more or less an executable statement.

No comments: