
Reader macros in Common Lisp - wtbob
https://gist.github.com/chaitanyagupta/9324402
======
seertaak
<rant> It's sad that clojure opted, for no good reason IMHO (ease of
implementation, perhaps?), not to allow reader macros. I know, they claim that
reader macros lead to "snowflake" code. But _this is lisp_. If you don't want
tweakability, go back to Java. </rant>

~~~
Guthur
Ease of implementation is an excuse for other things in Clojure as well,
single pass compiler comes to mind.

But I would give up all of these for an interactive debugger. The series below
shows how Common Lisp debuggers are light years ahead of the Clojure.

[http://malisper.me/2015/07/07/debugging-lisp-
part-1-recompil...](http://malisper.me/2015/07/07/debugging-lisp-
part-1-recompilation/)

[http://malisper.me/2015/07/14/debugging-lisp-
part-2-inspecti...](http://malisper.me/2015/07/14/debugging-lisp-
part-2-inspecting/)

[http://malisper.me/2015/07/22/debugging-lisp-
part-3-redefini...](http://malisper.me/2015/07/22/debugging-lisp-
part-3-redefining-classes/)

And this is important. I develop Clojure for a day job and this is a constant
PITA.

~~~
brandonbloom
Ease of implementation is not the reason for either no reader macros or a
single pass compiler.

Rich Hickey discusses reader macros here: [http://clojure-
log.n01se.net/date/2008-11-06.html](http://clojure-
log.n01se.net/date/2008-11-06.html)

Quotes:

"Clojure doesn't allow user-defined reader macros because they can't be
combined - there's no namespace support, unlike for regular macros"

"CL has user reader macros and the consensus is to avoid them"

"you are unlikely to convince me they are a good idea"

"I recognize fully this is less flexible than CL in this area, OTOH, I'd like
to think Clojure will engender less desert-island programming than did CL --
speaking a common language fosters library development, shared idioms etc.
When everyone creates their own language there's less of that"

"and even standard reader macros pose an understanding challenge for
newcomers"

Compilation units are discussed here:

[https://news.ycombinator.com/item?id=2467359](https://news.ycombinator.com/item?id=2467359)

------
ohpauleez
While there are no first-class reader macros in Clojure, reader literals cover
many common use cases. For the small set of use cases where you REALLY need
reader macros, it's possible to hack them into the language. One such
implementation: [https://github.com/klutometis/reader-
macros](https://github.com/klutometis/reader-macros)

As far as interactive debugging - that's also something I missed from CL, but
is relatively easy to hack into the language. A combination of REPL support
for the standard JVM debugger
([https://github.com/ohpauleez/cdt](https://github.com/ohpauleez/cdt)), with a
nice expression-based REPL debugger
([https://github.com/ohpauleez/cdt/blob/master/src/cdt/debug_r...](https://github.com/ohpauleez/cdt/blob/master/src/cdt/debug_repl.clj))
gets you pretty far. You can even trigger this environment on any exception
using the built-in JVM support
([https://gist.github.com/ohpauleez/4ca0b646b89512f38ea2#file-...](https://gist.github.com/ohpauleez/4ca0b646b89512f38ea2#file-
debugrepl-clj-L96-L108))

To see how far you can take reader literals, hack a look at my talk from last
year's Conj, "Unlocking Data-driven Systems" \-
[https://www.youtube.com/watch?v=BNkYYYyfF48](https://www.youtube.com/watch?v=BNkYYYyfF48)

~~~
armitron
Interactive debugging is not "relatively easy to hack into the language". In
fact, it's impossible since Clojure lacks the Common Lisp condition system.

When an exception is thrown in Java, _the stack unwinds_ meaning all state in
stack frames from the point of the throw to the handler gets thrown out.

In Common Lisp, _the stack does not unwind_ and high level logic can simply
restart the computation (after fixing the error or trying different
strategies) without losing any intermediate state. This killer feature is what
makes interactive debugging possible.

Hacks like the one you linked to are a sorry state of affairs compared to what
I described.

~~~
ohpauleez
While I appreciate the dialog, your comment is rather condescending. I've
worked extensively in Common Lisp and am well aware how the condition system
works. My claims had little to do with conditions, and more about the benefits
and use - It's pretty simple to have a dynamic var (say, _handler_ ), bound to
anything you like, catching errors before the stack unwinds, including an
expression-based REPL debugger, allowing you to change locals and return a
value in the place of the exception. It has all the limitations you can
imagine, but for many cases, this is plenty to be effective.

------
arethuza
Reader macros are brilliant - but as with many powerful language features they
should be used carefully. I vividly remember receiving a release of some code
(early 90s - a tape in the post) and looking at it and thinking that the
source wasn't Lisp at all. Turns out it was someone who invented their own
syntax and implemented it all as reader macros on top of Lisp - not quite as
bad as trying to turn C into Pascal with #defines though but in a similar
spirit.

~~~
sklogic
And what is wrong, exactly, with changing the language syntax?

DSLs become more readable and closer to the way the problem domain experts
think if they are using the more convenient syntax.

~~~
jlg23
There is nothing wrong if you can justify it to the next programmer who has to
deal with your code. If your gain is only marginal but I have to read and
understand 200 lines of code to understand your DSL, I might be mildly
annoyed....

~~~
sklogic
A well-designed DSL should be self-documenting and obvious. And the right
tools (like a proper IDE integration, with syntax highlighting and
autocompletion) would make such a DSL much more obvious than a library of
functions (which still must be thoroughly documented to be usable).

~~~
zzalpha
_A well-designed DSL should be self-documenting and obvious._

ROFL. You're adorable. :)

You're also conveniently ignoring the maintenance required on the DSL itself.
DSLs are, themselves, code, and code must be tested, updated, will likely
experience regressions, etc.

~~~
sklogic
I've been building properly designed, syntactically rich DSLs for over a
decade. It is much, much easier than building usable APIs.

DSL compilers are the simplest and cleanest code possible. They're nothing but
a chain of very trivial tree rewrites, and with a help of a proper DSL you can
write and maintain them easily.

------
jordigh
So if lisp is so great and so are reader macros, why didn't Macsyma/Maxima win
over Mathematica? It _is_ just a bunch of reader macros and lisp, right? It
seems like a CAS is a prime use case for lisp to really shine.

Why isn't anyone else writing new CASes in lisp?

~~~
bitwize
Because Lisp ran like shit on even the high-end hardware of that day. Plus it
was proprietary -- nothing like SBCL existed. By using C Wolfram was able to
offer a much more performant system with much lower TCO. Combine that with his
legendary self-promotion skills and you have a juggernaut in the marketplace.

~~~
hga
Maclisp ran quite fast on the PDP-10, even faster than DEC's FORTRAN (for a
while, DEC was sufficiently embarrassed they put more effort into it).

High quality Lisps being proprietary during the chaotic '80s through the
early-mid '90s was certainly an issue for Maxima, but for the licensed Macsyma
(see my other comment on the history) I _think_ that would have been an
acceptable part of the cost of goods; too bad Symbolics demanded you by one of
their Lisp Machines to run it for too long.

Self-promotion ... yeah, Mathematica wins hands down there ^_^.

