

Introducing lisp.js: a Lisp for node.js - devijvers
http://lisp-js.posterous.com/lispjs-a-lisp-for-nodejs-0

======
gruseom
While it's always great to see experimentation in the Lisp realm, I'm unclear
as to what "a Lisp for node.js" will do that the mature Lisp-on-top-of-JS
(Parenscript) doesn't already do.

~~~
jashkenas
There's also already a Lisp-on-Node project called Sibilant. Jake's got a neat
live-compile-in-the-browser demo up here:

<http://sibilantjs.info>

And the source is available here (and as an NPM package):

<http://github.com/jbr/sibilant>

~~~
gruseom
I went through the demo and have the same question about this: why greenspun
Parenscript in this manner? It does all these things, and zillions more, in a
nice way. The only reason I can think of is fun, which is perfectly
legitimate. Or maybe people don't want to run Common Lisp even to compile
their code?

~~~
avibryant
Some reasons I can think of: it's definitely an advantage to be able to
compile the code on the client-side, which sibilant should be able to do; I
don't know if Parenscript can bootstrap itself the same way. Some people, like
me, prefer lisp-1 to lisp-2. Being less like Common Lisp and more like
Javascript can be an advantage; sibilant seems to support foo.bar notation for
accessing JS properties, which I think is the right choice in this context (I
would also like to see JS/JSON literal syntax supported).

All of the docs on Parenscript seem to assume you're using it to render bits
of JS and HTML from a Common Lisp server. It would be useful if there were a
tutorial that showed how to use Parenscript for this use case, simply to
compile lisp-like code into standalone JS files for use with whatever
arbitrary backend.

~~~
gruseom
Yeah, perhaps I'll write something that once we have a bit more experience
with server-side PS.

Interesting what you say about foo.bar; PS originally did that, and I was one
of the people who lobbied against it. It does make getting started a little
easier, but interferes with macros down the road. For example, if you want to
do anything like transforming foo.bar to foox.barx, you end up having to parse
the symbols to split them, which seems wrong. Since Lisp-style metaprogramming
is pretty much Parenscript's raison d'être (well, that and interoperability
with CL for the crazy few who care), it seems foolish to do anything to
compromise it.

~~~
avibryant
Why not consider it a reader macro, and translate it to (@ foo bar) or
whatever is appropriate, before applying macro expansion?

~~~
sedachv
I considered doing that, but it pretty much means rewriting the reader because
it changes the grammar so much. Not that it's not possible, I just don't trust
myself not to make it full of bugs.

------
mark_l_watson
I like this! I just put a reminder on my calendar for 3 months from now to
more-fully check out the project.

------
maxtilford
Awesome. I've got it up and running. I've been looking for a solution for the
client/server distinction for a while. How much have you thought about the
implementation of that?

~~~
devijvers
Good to hear! What do have in mind when you say "client/server distinction"?

~~~
maxtilford
Mainly, I'm tired of using $.getJson, and I liked your on-server macro. Also,
how is the server going to watch references on the server and vice-versa?

~~~
devijvers
Basically, the server "knows" (as in can know) the references that exist on
the client and vice versa. When a watched reference changes value on the
client an HTTP request/response is sent over the wire. The request carries the
old and new value, the response is basically redundant but since it's HTTP it
needs to be there. Hence, the response might carry new forms to be executed on
the client.

The client watching references on the server is obviously more tricky. node.js
already supports keep-alive by default. There probably needs to be some kind
of chuncked reply mechanism that allows the server to send changes without the
client having to send polling requests. Obviously, if the reference is not
going to change frequently it might be cheaper to just poll every once in a
while.

------
DTrejo
_lisp.js will be a lisp-2 (like Common Lisp and unlike Clojure and Scheme)_

Can you talk more about this decision?

~~~
devijvers
Macros are important, that's why I seeking guidance in _Let Over Lambda_. The
most suitable lisps for writing macros are lisp-2, hence the preference for a
lisp-2 dual namespace.

~~~
pwpwp
Lisp-2's have _less_ potential for trouble with _unhygienic_ macros, but they
still have it. Hygienic macro systems work with Lisp-1 as well as with Lisp-2.

Apropos, I've written a Lisp->JS compiler a while ago; you might find some of
the code useful: <http://github.com/manuel/cyberlisp/>

~~~
sedachv
In regards to hygienic macros and Hoyte's Let Over Lambda, the type of
variable capture hygiene is designed to prevent is actually used as a
programming technique in the book; Hoyte calls it free variable injection.

Lisp-1 vs Lisp-2 actually has very little to do with macros. Most of the
inconvenience comes when writing functions - things like having to name list
parameters "lst." The way Common Lisp gets around the variable capture problem
is to forbid the rebinding of special forms, functions, and macros defined in
the standard.* This is an ugly hack that forces early binding, and obviously
does nothing to prevent capture of user-defined functions.

The Scheme wiki has a good article on hygiene:
<http://community.schemewiki.org/?hygiene-versus-gensym>

* - This wasn't done for the sake of macros. The rationale behind the decision as I heard it is to prevent the hypothetical scenario of some standard function like cdr that's called inside the garbage collector or allocator from being rebound to something that tries to allocate memory and crashes the gc or sends the allocator into an infinite loop. I don't really buy it; it's easy enough to prevent these types of scenarios.

------
tlrobinson
So you mean "Lisp for JavaScript"? Why limit it to node.js?

~~~
devijvers
It might one day become a general lisp for javascript but for now the
concurrency-free server-side environment of node.js is assumed.

