[ANN] Sibilant: Javascript with a lisp

85 views
Skip to first unread message

Jacob Rothstein

unread,
Jul 5, 2010, 9:09:05 PM7/5/10
to nod...@googlegroups.com
Hi there,

I wanted to announce my latest node project: Sibilant is a
lisp-inspired language that's parsed by node into javascript, a la
coffeescript. I've got a lot of documentation to write, but I wanted
to post this somewhere and solicit preliminary feedback.

If that sounds interesting, check it out at
http://github.com/jbr/sibilant, look at the example pairs
(http://github.com/jbr/sibilant/tree/master/examples/) and npm install
sibilant. Bikeshedding appreciated.

Thanks for node!
–Jacob

PS Is the general consensus that project announcements are okay on
this list or should we have something like a node-users list for
non-core modules & apps?

Scott Taylor

unread,
Jul 6, 2010, 10:11:00 AM7/6/10
to nod...@googlegroups.com

On Jul 5, 2010, at 9:09 PM, Jacob Rothstein wrote:

> Hi there,
>
> I wanted to announce my latest node project: Sibilant is a
> lisp-inspired language that's parsed by node into javascript, a la
> coffeescript. I've got a lot of documentation to write, but I wanted
> to post this somewhere and solicit preliminary feedback.
>
> If that sounds interesting, check it out at
> http://github.com/jbr/sibilant, look at the example pairs
> (http://github.com/jbr/sibilant/tree/master/examples/) and npm install
> sibilant. Bikeshedding appreciated.

Neat.

Any thought of doing tail recursion?

I'm sure you've also seen these projects:

http://www-sop.inria.fr/mimosa/scheme2js/
http://code.google.com/p/js-scheme/
http://common-lisp.net/project/parenscript/

How does it compare?

Scott

>
> Thanks for node!
> –Jacob
>
> PS Is the general consensus that project announcements are okay on
> this list or should we have something like a node-users list for
> non-core modules & apps?
>

> --
> You received this message because you are subscribed to the Google Groups "nodejs" group.
> To post to this group, send email to nod...@googlegroups.com.
> To unsubscribe from this group, send email to nodejs+un...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/nodejs?hl=en.
>

Jacob Rothstein

unread,
Jul 6, 2010, 11:44:24 AM7/6/10
to nod...@googlegroups.com
Truth be told, I hadn't seen js-scheme (the second on your list),
which is the most interesting of the similar projects, since it's
written in javascript. I'm going to read it through for ideas, but it
seems very browser-oriented (depends on jQuery and prototype -
http://code.google.com/p/js-scheme/issues/detail?id=17). The author
does have a very nice browser-based repl, though, and the code seems
very well factored.

The others don't appeal to me because they're not written in js.
There are a number of neat things about writing and evaluating to the
same language, particularly when that language has metaprogramming
abilities like eval. This allows us to modify the interpreter at
compile-time with defmacro, which translates the contents, evals that,
and makes it available to any code interpreted afterwards. This means
that language users can change implementations of nearly anything from
inside the language. Don't like the way "if" or "dolist" are
implemented? You can change that without having to drop into JS or
modify the interpreter code. As an example, maybe you'd like (= ...)
to mean javascript's == instead of === for some odd reason. You could
stick

(defmacro = (lhs rhs)
(concat "(" (translate lhs) " == " (translate rhs) ")"))

At the top of your code and for the rest of that interpreter run,
you've got an == operator. (= 1 2) will output "(1 == 2)"

As far as TCO, I've been thinking about that since last night. I've
got a hacked version working with TCO that at least handles the
TCO-optimized fibonacci example I've been using as a start. I'm
working on turning it into a module that has to be opted into. The
idea of the implementation is:

When you define a function, it checks if the name of the last call is
the name of the function you're defining. If so, it would change
countdown = function (down, up) {
if (down === 0) {
return up
} else {
return countdown (down - 1, (up || 0) + 1)
}
}

into

countdown = function (down, up) {
var down, up
var _down, _up
__TCO__countdown:
while(true) {
if (down === 0) {
return up
} else {
_down = down - 1
_up = (up || 0) + 1
down = _down
up = _up
continue __TCO__countdown
}
}

That's currently working locally. I've never used labeled continues
before, but they seem to work okay for this. Does that seem like a
reasonable way to do TCO?

–Jacob

Isaac Schlueter

unread,
Jul 6, 2010, 1:53:34 PM7/6/10
to nod...@googlegroups.com
A TCO implementation should support something like this, counting to
infinity with constant memory usage:

function A (n) {
console.log(n)
if ( n < Infinity ) return C(n+1)
else console.log(n)
}
function B (n) {
return A(n || 0)
}
var C = B
C()

That is, TCO isn't necessarily about *recursion*, per se, but rather
about *any* kind of tail calls, including to other functions, even if
they weren't declared as functions initially.

--i

Scott Taylor

unread,
Jul 6, 2010, 2:00:20 PM7/6/10
to nod...@googlegroups.com

That seems like a problem unless you do some sort of gensym type thing with those symbols (think of a let expression that rebinds a name within a scope).

I also have no idea if that would be a scheme compliant TCO. I'm pretty sure the spec says _all_ tail calls, which would include weird constructs like the Y combinator where the lambdas aren't bound to a name. I'm no expert at scheme, though, so don't take my word for it.

Otherwise, as for TCO, there are a bunch of people who have done it (even for js), and I'm sure you can steal some good ideas from them:

http://glathoud.easypagez.com/publications/tailopt-js/tailopt-js.xhtml
(and http://glathoud.easypagez.com/publications/tailopt-js/tailopt.js)
http://c2.com/cgi/wiki?ImplementingLisp
http://www-sop.inria.fr/mimosa/scheme2js/files/tfp2007.pdf (and you might generally want to look up trampolining for TCO)

And finally, a really simple solution: don't implement it. It's a lisp, but not a scheme, so as long as no one is under the impression that there are tail calls, no one will use tail-call constructs.

Scott

Isaac Schlueter

unread,
Jul 6, 2010, 2:08:10 PM7/6/10
to nod...@googlegroups.com
On Tue, Jul 6, 2010 at 11:00, Scott Taylor <sc...@railsnewbie.com> wrote:
> I also have no idea if that would be a scheme compliant TCO.  I'm pretty sure the spec says _all_ tail calls, which would include weird constructs like the Y combinator where the lambdas aren't bound to a name.  I'm no expert at scheme, though, so don't take my word for it.

Yes, that is exactly the point of TCO. It must affect *all* lambdas,
especially anonymous ones. (Should've put that in my example.)

> http://glathoud.easypagez.com/publications/tailopt-js/tailopt-js.xhtml
>        (and http://glathoud.easypagez.com/publications/tailopt-js/tailopt.js)
> http://c2.com/cgi/wiki?ImplementingLisp
> http://www-sop.inria.fr/mimosa/scheme2js/files/tfp2007.pdf (and you might generally want to look up trampolining for TCO)
>
> And finally, a really simple solution: don't implement it.  It's a lisp, but not a scheme, so as long as no one is under the impression that there are tail calls, no one will use tail-call constructs.

Absolutely. We've been getting by without TCO in js for some time
now. But it'd be neat.

--i
http://twitter.com/izs/status/17835515459

Jun

unread,
Jul 7, 2010, 11:35:25 PM7/7/10
to nodejs


On Jul 6, 7:11 am, Scott Taylor <sc...@railsnewbie.com> wrote:
> On Jul 5, 2010, at 9:09 PM, Jacob Rothstein wrote:
>
> > Hi there,
>
> > I wanted to announce my latest node project: Sibilant is a
> > lisp-inspired language that's parsed by node into javascript, a la
> > coffeescript.  I've got a lot of documentation to write, but I wanted
> > to post this somewhere and solicit preliminary feedback.
>
> > If that sounds interesting, check it out at
> >http://github.com/jbr/sibilant, look at the example pairs
> > (http://github.com/jbr/sibilant/tree/master/examples/) and npm install
> > sibilant. Bikeshedding appreciated.
>
> Neat.
>
> Any thought of doing tail recursion?
>
> I'm sure you've also seen these projects:
>
> http://www-sop.inria.fr/mimosa/scheme2js/
> http://code.google.com/p/js-scheme/
> http://common-lisp.net/project/parenscript/

Not to mention ClojureScript:

http://github.com/richhickey/clojure-contrib/tree/master/clojurescript/

Jun
Reply all
Reply to author
Forward
0 new messages