Wisp: a homoiconic JS dialect with Clojure syntax, s-expressions and macros
jeditoolkit.com
jeditoolkit.com
If you want a JavaScript with Lispy syntax, there are a few things like http://lispyscript.com/ -- Spiritually similar to CoffeeScript. But if you want Clojure semantics, there is ClojureScript: Very different than a simple transpiler like CoffeeScript. ClojureScript includes a standard library of rich data structures and utility functions.
But why would you want Clojure syntax without Clojure semantics? Especially since Clojure syntax implies several data types that JavaScript can't provide natively. It just doesn't make sense...
Of course this means that some of Clojure's features (protocols and lazy sequences, atoms, etc.) are not available. On the other hand there are not so many opaque layers between your code and the target code.
Granted feature-wise it might be more similar to a scheme, but Clojure Syntax is so much more readable and I do not see a point why it would not be a valid approach.
As a matter of fact I plan to provide protocols lazy sequences etc.. in form of (optional) libraries that can be included or omitted based on user use cases. I personally thing that most of these features are drawbacks when interacting with JS code, although I'd definitely used them in cases where interaction with JS is not a concern.
Update:
Also, on the projects web site [0], it says that "Homoiconic syntax and macros are the primary motivations!"
[0] https://github.com/Gozala/wisp
I don't know how this project is in practice, but I think those goals are worthwhile. When it comes to Clojure proper, one of the many selling points is that it does Java better than Java. This project may be able to do the same for Javascript.
Clojurescript's heavy dependence on the Clojure environment (JVM, leinigren etc) make it a real pain to get setup for. I have looked into clojurescript several times but thought "I better master clojure first". I have been getting a hang of Clojure slowly and plan to tackle learning clojurescript eventually but something like Wisp opens up the possibility of diving in without needing to be comfortable with all the Java crap.
I only tend to take up something when it takes me five minutes to start learning. I think most are the same way; it's the reason why Codecademy is so popular and why clojurescript's primary user base is Clojure users. The more users that can start learning a language in five minutes the better it is for that language. Clojure beat out other Lisp implementations primarily because it was easier to dive into for a greater number of humans than any other Lisp.
Wisp and other implementations like it make diving into Lisp->js languages much easier. It removes the large roadblock that is Java, a roadblock that is unnecessary if your target language is JS not Java.
Wisp looks like Javascript was supposed to look before they bolted C syntax onto it. People say that Javascript is like Scheme with C syntax. So Wisp is like Javascript with Scheme syntax. I think this is something I would actually use.
I didn't know about LispyScript either, though. I would have to compare/contrast the two.
Wisp, I guess provides readable js as opposed to compiled js. That's a win.
I was pretty dissapointed with ClojureScript because it generates almost unreadable JavaScript; It includes an extremely heavy library that most people don't use and would never use; It depends on a lot of JVM specific things. For it to be a lot more successful as a compile-to-javascript platform it would need to move closer to native JavaScript than anything else.
> Unlike clojurescript, wisp does not depends on JVM and is completely self-hosted. It compromises clojure's awesome data structures and embraces native JS data structures to be a better at cooperation with JS. Goal of wisp is to present a subset of clojure(script) language such that packages written in wisp can be consumed natively by wisp, clojure(script) and JS when compiled, without data marshalling or any code changes.
While I do like clojure(script) a lot I don't think it makes too hard to consume data structures from JS land and makes consuming data produced by clojure(script) awkward for consumption on the JS side. That is a the reasonable compromise for a great power, it's just I think I'd rather leverage JS data structures in immutable manner directly and provide more clojure like data structures in form of libraries. This would allow users to make best (or maybe worst) choices based on their constraints.
As of lispyscript it's nice project and as a matter of fact wisp is just a fork that never got merged in to upstream. I was convinced that clojure (or any other known lisp) syntax was better option than yet another new lisp. In addition I wanted full macros that unlike wisp lispyscript does not has. Also lispyscript has no lists, instead it uses arrays and I can continue this list over and over...
> But why would you want Clojure syntax without Clojure semantics? Especially since Clojure syntax implies several data types that JavaScript can't provide natively. It just doesn't make sense...
JS can do it otherwise clojurescript won't be possible, I just think these data types can be exposed via optional libraries as they have associated cost in terms of performance overhead and learning curve.
And to be quite honest I do hope that a lot of wisp parts will find it's way to clojurescript, it's just contributing to clojurescript turned out to be harder than bootstraping own version, since even pull requests for travis-ci integration tests require lot's of justification.
Does not compute! :P
> ClojureScript compiler is implemented in Clojure, which runs on the JVM
that pretty much sums up my experience with ClojureSctipt as well.
\a ;; compiles to "a"
:a ;; compiles to "a"
"a" ;; compiles to "a"
This is not meant as destructive criticism; I'm genuinely interested in the motivation for that. public class Keyword implements IFn, Comparable, Named, Serializable, IHashEq
https://github.com/clojure/clojure/blob/master/src/jvm/cloju... \a ;; becomes 'a' in java. The character of 'a'
:a ;; a keyword of :a. More efficient than using 'a'. Also it can act as a function. If you have a map with a key of :a in it, instead of having to say "get me the value for :a" you can say (:a map)
"a" becomes "a" in java. The string of "a"The coolest thing about :keywords in Clojure is that they really are functions and you can do things like (map :keywords ontoSomething) to extract the same property out of many things. It don't work in Wisp.
That's basically what keywords do -- they are human-readable and compile down (prob. using some hash) into some integer, and the integer is stored globally only once. The biggest savings in memory comes when using maps, and that's how & why keywords get their name.
Also, Java declared java.lang.String as final, so Strings can't be extended to implement clojure interfaces to get nice behavior, like IFn and IKeywordLookup.
Ok. That sucks. So pretty much anyone already a bit serious about Clojure wont be enticed by this then.
Edit: From the page:
;; Keywords can be invoked as functions, that desugars to plain
;; associated value access in JS
(:bar foo) ;; => foo["bar"]
That seems pretty close to what's expected though, doesn't it? user=> (type \a)
java.lang.Character
user=> (type :a)
clojure.lang.Keyword
user=> (type "a")
java.lang.String
The only unusual thing is the keyword. Fogus and Houser say this: "Because keywords are self-evaluating and provide fast equality checks, they're almost always used in the context of map keys." But here you're back to checking equality of strings. Not sure if the same is true for ClojureScript.You can also use them as functions to look up values in maps. For example:
user=> (:my-key {:other-key 1, :my-key 2})
2
There are other places they're used--for example, list comprehensions with `for`: (for [x (range 10)
y (range 10)
:when (= x y)]
[x y])
=> ([0 0] [1 1] [2 2] [3 3] [4 4] [5 5] [6 6] [7 7] [8 8] [9 9])
In Clojure keywords are nice to have.As of :a keyword it's a different story. As a matter of fact actual (quoted) keyword ':a does not compiles to "a" string, but general references do. That is because in JS constant string literals like "load", "DOMContentLoaded" are used in cases where idiomatic Clojure(script) would have used :load :DOMContentLoaded keywords, there for it made sense to just compile those keywords to semantical analogues in JS, same as `foo-bar` lisp naming convention compiles to adequate `fooBar` naming in JS.
As a non-lisp guy who doesn't know any better (me), good job.
Which is basically a subset of common-lisp that compiles to human-readable javascript. It's a good idea.