Why fork - Gozala/lispyscript GitHub Wiki
Initially fork of lispyscript was created to contribute improvements & bug fixes to an original lispy repository, but in the process few decisions have driven it to an incompatible direction. This document attempts to elaborate reasons and hopefully motivate unification.
Note: Some of the outlined points may present work in progress plans that are not yet implemented. They will have appropriate notes.
1. Clojure syntax
In contrast to main lispy repository that defines it's custom lisp syntax, this fork enables and also encourages clojure(script) syntax instead (while keeping backwards compatibly with lispy). This provides certain advantages:
-
All the tooling build by a clojure community (syntax highlighters, editors, …) becomes automatically available.
-
Unlike other lisps, clojure is little lighter on parentheses
()by employing curly braces{}& square brackets[], which makes code easier to read. -
Bunch of code has already being written in clojure(script), same syntax enables code reuse.
-
Clojure(script) has active community, that will have no barrier on using lispy if it had same syntax.
Examples
;; Variables
(var foo "bar") ;; Lispy
(def foo "bar") ;; Fork
;; Lambdas
(function (a) (+ a 1)) ;; Lispy
(fn [a] (+ a 1)) ;; Fork
;; Functions
(var inc (function (a) (+ a 1))) ;; Lispy
(defn inc [a] (+ a 1)) ;; Fork
;; Method calls
(console.log "Hello LispyScript!") ;; Lispy
(.log console "Hello LispyScript!") ;; Fork
;; Property access
(.location (open uri)) ;; Lispy
(.-location (open uri)) ;; Fork
;; Setting values
(set foo "bar") ;; Lispy
(set! foo "bar") ;; Fork
;; Macros
(macro when (cond rest...) ;; Lispy
(if ~cond (do ~rest...)))
(defmacro when [condition & body] ;; Fork
`(if ~condition (do ~@body)))
2. Conventional code
Lispyscript embraces JS conventions, like cammelCase, isPredicate style etc… Which feels little awkward for lisp dialect. In contrast this fork embraces dash-delimited and predicate? style that is translated to conventional cammelCase, isPredicate JS style.
Examples
(set xhr.onReadyState stateHandler) ;; Lispy
(set! xhr.on-ready-state state-handler) ;; Fork
Both compile to:
xhr.onReadyState = stateHandler
3. Arity base dispatch
Lispyscript get's out of it's way to be homoiconic JS with macros. While this fork shares same goal, it takes a step forward and provides arity based dispatch for macros and functions (functions don't have it yet) as an alternative to painful arguments based code branching.
Examples
(defmacro def
"Defines a varible with given initial value or undefined"
([name] `(def ~name (void)))
([name value] (js* "var ~{}" (set! ~name ~value))))
4. Commas are optional
This fork treats , (similar to clojure) as a whitespace. This allows lighter syntax for JS arrays. Same is planned for dictionaries - JS objects.
5. () are lists, [] are vectors / JS Arrays
Unlike original lispy () represents lists and [] represent vectors - JS arrays. (This is not fully baked in yet)
6. Keywords
Clojure has keyword data structure, that is typically used to for parametric flags: :ready, :loading. In JS this is usually substituted with a string constants: "ready", "loading". This fork supports keywords translating them to analogous strings to match JS conventions. This allows more expressive highlighting difference between constants and plain strings.
Examples
(window.addEventListener "load" loadHandler) ;; Lispy
(.add-event-listener window :load load-handler) ;; Fork