This is pretty cool.
Apache is a huge pain to set up, good call on Node.js. I like how short the glue code is.
You should probably go with a Lisp process per session.
Consider using CLISP because it starts up really fast and has very little memory overhead (although both CLISP and SBCL share their Lisp image VM pages, loading FASLs causes some of the pages to be modified and unshared - if you make a new image file with Parenscript preloaded, all the processes will share their entire image).
The tricky thing is going to be detecting a stuck process. One easy way to bypass this is to do a new Lisp process per eval - just run the entire REPL history over every time the user presses enter, and have something like a 5 second timer that kills that process if it doesn't complete. I guess that's exactly like CGI. Users might run into trouble if something depends on randomly generated names (gensyms should be identical across invocations).
You can use FreeBSD jails or one of the Linux jail tools to sandbox the Lisp and allow defmacros (although the latter are kind of a pain to set up).
As far as the code goes, the repository Parenscript has implicit returns for defuns and lambdas. I should put together a new release soon.
Vladimir
2010/7/23 Nick Fitzgerald fitzgen@gmail.com:
Hey guys! I just got a quick and dirty first iteration of http://tryparenscript.com/%C2%A0up and running. Emphasis on dirty. This is my first "real" piece of ParenScript, so I would love to have some feedback. All of the code is hosted at http://github.com/fitzgen/tryparenscript.com It follows in the footsteps of http://www.tryruby.org/,%C2%A0http://tryhaskell.org/, and http://tryclj.licenser.net/. Basically provides a REPL for ParenScript inside of your browser. I would like to add an interactive tutorial like how some of those have in the future. I couldn't get sbcl and hunchentoot running behind apache, it was a nightmare for me (though I expect I just was overlooking something), so I ended up writing the backend in ParenScript too, with Node JS. Currently there are some issues with the way that function definitions are evaled in the global scope, so (defun foo (x) (return (+ x 1))) won't create a new global foo function because it ends up being evaluated as this: window.__tryps_return = function foo(x) { return x + 1; } so what should have been a Function Declaration gets turned in to a Named Function Expression. This is on the top of my list of things to do next. Fortunately, there is a simple (while not quite "easy-to-use") fix: (setf (@ window foo) (lambda (x) (return (+ x 1)))) which will work as expected. I also expect I will need to set up some type of monitoring for the server because it is just a single process in detachtty, and if it crashes (which I suspect it might if it hit the front page of Hacker News all of a sudden, or something like that) I would have to go back in and restart the process (after I somehow found out it died). This is obviously less than optimal. If anyone has any suggestions on this front, I would love to hear them too. Most of all, I would just like to get some feedback and suggestions on the code :) Thanks in advance for all your responses!
_Nick_
parenscript-devel mailing list parenscript-devel@common-lisp.net http://common-lisp.net/cgi-bin/mailman/listinfo/parenscript-devel