Show HN: Eslisp – Minimal JavaScript S-expression syntax and macro system
github.com
github.com
While my server still works well, it's obvious Node and JS have become predominant tools in the space. I used these tools for my most recent project and while not too difficult to get up to speed, it lacked the elegance and simplicity I preferred.
Eslisp looks promising, surprisingly close to Lisp/Scheme I'm familiar with. I'm thinking that a few changes might make it even closer. For example, one could use "define" instead of "=" to declare bindings, or "begin" instead of "block".
The "this" syntax in macros is reminiscent of the arguments to ER syntax transformers which can be used to operate on elements in macros. Is it possible to simplify it further? Something like (this/evaluate) instead of (. this evaluate)?
Just ideas that pop into mind...
I agree that using s-expr syntax to create macros makes is much better than the elaborate syntax of other JS macro systems. I'm looking forward to learning more and trying it out.
Eslisp looks like it will be excellent.
> Lisp's hierarchical list notation is by far the most natural, intuitive way to represent HTML.
HTML-representation is also important to me, and it's how I got started on eslisp actually. I wrote an XML templater https://github.com/anko/whatxml for LiveScript that abused the ".." cascaded-function-call feature to create XML hierarchies. It took me a while to realise it was basically an S-expression in disguise!
I'm working on an "eslisp-html"-macro that compiles to an HTML-templating function. Here's the gist of it so far https://gist.github.com/anko/f8ecc66a99a8ec656b49 No implementation yet, just an early-ideas readme with an example. What do you think?
> For example, one could use "define" instead of "=" to declare bindings, or "begin" instead of "block".
If you want to use different names for the built-in macros, you are welcome to. Aliasing them is just a matter of "(macro define =)", then "define" does the same as "=".
> The "this" syntax in macros is reminiscent of the arguments to ER syntax transformers which can be used to operate on elements in macros. Is it possible to simplify it further? Something like (this/evaluate) instead of (. this evaluate)?
Property access can be sugared to "this.evaluate" with the eslisp-propertify macro https://github.com/anko/eslisp-propertify It's quite convenient if you use it as a transform macro https://github.com/anko/eslisp/blob/master/doc/how-macros-wo... from the command line, like this https://github.com/anko/eslisp-fancy-function/blob/master/ma... Is that what you mean?
Interesting! Similar to Scheme templates:
(let* ((admintype (...))
...
(htm (htdoc
`(html
(head
(meta (@ title "My site")))
(body
(div (@ class "banner")
(img (@ class "logo" src "logo.gif"
title ,(get-curr-url))) ...
Basically it just sets up variables for use in the let* scope, and calling the htdoc procedure that parses the quasiquoted list, returning the prepared html as a string (written to the client-connected socket).The htdoc proc is surprisingly simple, and I've implemented it in other Lispy languages without much trouble. I'd be real interested to try it in Eslisp once I'm familiar enough with it.
> Property access can be sugared to "this.evaluate" with the eslisp-propertify macro ... Is that what you mean?
Possibly. I need to learn it more thoroughly.
Of course I realize the "(. id1 id2 ...)" form expands to object notation. My comment just reflected that to me the leading dot expression looks "noisy", a bit distracting.
In Scheme, identifiers can contain punctuation like ".", so "this.evaluate" could name a procedure, macro, etc. To my eyes, "(this.evaluate)" is visually easier to parse. In my head, the string "this.evaluate" looks like an atom that expands to the operator this.evaluate(), which I think is what it means.
I'm sure I'll get used to the notation as it is, this is just my immediate impression. However, mildly "sugaring" the representation might make it more accessible, especially to people not already enlightened by and in awe of the magic of s-expr.
Edit: getting the code section to look like code...
I can't think of a way to say `(html (body (p "hi")))` as clearly in pure JavaScript.
Avoid macros if at all possible. Use functions if you can.
Special forms that don't follow the standard evaluation rules are putting additional mental load on the readers of your code. If you go overboard with macro use, good luck having other people understand your code.
If you are a lone coder, feel free to go happy-crazy with macros. If you are a team, just stay with standard lisp as long as you can.
Heavily DLSed code is much more readable and maintainable than your mess of functions.
http://planet.racket-lang.org/package-source/dherman/javascr...
The Javadot notation was really convenient -- might be worth checking out:
PJS is very neat and its documentation very clear. I'm surprised how little JavaScript has changed in 16 years…
I've got a Javadot-like thing https://github.com/anko/eslisp-propertify for converting a.b.c → (. a b c). Eslisp uses "." for property access, like PJS' "field". It hasn't got a next-line (.property args) thing though, which seems useful. I'll be trying that.
Sweet.js macros are special-case separate structures that have to introduce special syntax, pattern-matching rules and a whole lot of other cruft, mainly to deal with JavaScript not being homoiconic.
tldr eslisp macros are prettier, otherwise quite similar.
All you need is to npm install it and do
(macro function (require "eslisp-fancy-function"))
If you want it in all files, it's safe to cat that onto the start of each as a build step.I do see your point though—it's a very common thing for people to want to use. I'm adhering strictly to UNIX design priciples for now because I'm afraid of featuritis, but perhaps that will change as the project matures.
I'm playing with the idea of having a separate convenience "getting started" package called "eslisp-coffee" or something, which acts like the core eslisp compiler but with a certain set of macros attached by default. What do you think?
Here's a brief comparison to a few other JS-lisps too: https://github.com/anko/eslisp/blob/master/doc/comparison-to...
Fixed, you can remove this line :)
I wrote a brief comparison in the docs: https://github.com/anko/eslisp/blob/master/doc/comparison-to...
Seeing ParEdit in action makes me extremely jealous though. http://danmidwood.com/content/2014/11/21/animated-paredit.ht... I wonder if the vim plugin https://github.com/vim-scripts/paredit.vim is any good.
Never tried the paredit vim extension, but I've heard a few people happy editing clojure/lisp under vim so I'm sure it's more than OK.
Best way to start a flamewar on IRC: "the difference between emacs and vi doesn't really matter"
Luckily, this won't happen here xD
https://youtu.be/4YfkwfZ7AV4?t=1521
Don Stewart, haskeller, talking about is editor of choice, vi, emacs, Yi, and the eternally self reemergent struggle.
I use only % operator, set sw = 2, visual > or < to edit lisp forms and I am very happy!!!
What does %, > and < do in your setup ?
An emacser wrote a thing called lispy to have vi-like sexp manipulation UX (aka single letter commands).
Using d% on (bar baz) then move to desired loc, and p. So % is for matching ( ). Again v% visually selects a form, then < and > for indent and dedent.
I wanted to write JS macros in JS, hence eslisp.
This is a neat project regardless.
[1] http://www.shenlanguage.org/
[2] https://www.youtube.com/watch?v=lMcRBdSdO_U