|February 5th, 2009|
|lisp, programming, shell, tech|
Bash is REPL based. As I build things up in bash that are quite complex I'm always testing as I go. I'll cat a bunch of files, pipe to something else, and if I get anything wrong I notice almost right away. This is very powerful because
Bash puts arguments first. I start with the files I want
to work with (
cat logs/tuesday/*) then pipe to grep to
filter out the ones I don't want, then maybe pipe to wc. All
along the way, I can print out what I have so far. And I can
think about the data before the next processing step. Some things
break this pattern, for example "
for x in $(big long
expression)" or "
diff <(determine A) <(determine B)"
but the former can be replaced with "
big long expression |
while read x" as long as it's not spaces you want to split on.
And the latter necessarily takes two input streams, so you have to
accept some loss of linearity.
This is not to say I think bash is ideal. The way it deals with unset variables (evaulating to the empty string) is pretty annoying. And always having to worry about special characters doing crazy things is also frustrating. And the things I write are rarely easy for even me to read looking back on them after a while. But it's definitely fast to write.
Lisp shares the first property with bash, but in the other it's
nearly the opposite. The analog of "
cat | grep | wc" is
(wc (grep (cat)))". Most languages are niether all one
way or all the other. They can go "
a = cat(); b = grep(a); c = wc(b)" and most programmers
use some of both.
Thinking about how easy it would be to write inverted lisp with a
reversing macro interpreting everything (not that I actually think
this is better -- the top down style of lisp with more thinking
ahead is probably good for me) brought me on to the other idea: it
might not actually be good for languages to be as extensible by
the individual programmer as lisp is. Paul Graham writes that a
language annoyance that a java or python programmer would have to
wait for a language fix for a lisp programmer can generally just
fix themself. Take generics in java or, better,
python. It's really nice. Instead of having to remember to close
things or release locks even in complex error situations, they're
dealt with when the block ends. But it wasn't in python for a
long time and had to be centrally added. In lisp anyone could
with and not have to wait. This sounds good.
Except that in the lisp case only that person benefits; any one
who didn't think to write
with doesn't get to use it. In
python it became available to everyone. Because smart people who
want to have an extended version of the language can't just do it
themselves easily, they suggest it as a feature and everyone gets
it. Maybe this isn't ideal, but it improves the core language
much faster. Looking at arc, I think almost all of it could be
implemented entirely as macros and functions in common lisp.
And many of the good ideas probably have been implemented in lisp
by many people over and over. But without the pressure of
users frustrated by the limits of the language, lisp didn't get
Comment via: facebook