-
Notifications
You must be signed in to change notification settings - Fork 15
Differences from Clojure
What follows is a section-by-section review of the sections on the left-hand navigation panel of http://clojure.org, enumerating what is different in ClojureScript and in some cases the similarities.
The rationale for ClojureScript is much the same as for Clojure, with JavaScript in the role of platform, and additional emphasis on the reach of JS, as it is obviously not as rich a platform.
A deeper discussion on ClojureScript's rationale can be found elsewhere on this site.
Same as Clojure. Clojure's identity model is simpler and more robust than mutable state, even in single threaded environments.
ClojureScript's REPL can be launched from within the Clojure REPL. See Quick Start for details.
ClojureScript has the same immutable persistent collections as Clojure on the JVM.
ClojureScript's macros are written in Clojure, and are referenced via
the require-macros
keyword in namespace declarations:
(ns my.namespace
(:require-macros [my.macros :as my])
The :as prefix
selector is required in :require-macros
. One point of note is that the code generated by ClojureScript macros must target the capabilities in ClojureScript.
- ClojureScript protocols have the same semantics as Clojure protocols.
Clojure's model of values, state, identity, and time is valuable even in single-threaded environments.
- Atoms work as in Clojure
- No Refs nor STM
- The user experience of
binding
is similar to that in Clojure- There are no Vars
- not reified at runtime
- many development time uses of reification are obviated by access to Clojure data structures via the analyzer
-
def
produces ordinary JS variables
- There are no Vars
- Agents are currently not implemented
- ClojureScript is hosted on JavaScript VMs
- Optionally, it may use Google's Closure compiler for optimization
- It is designed to leverage Google's Closure library, and participates in its dependency/require/provide mechanism
See Quick Start
- Numbers
- ClojureScript currently only supports integer and floating point literals that map to JavaScript primitives
- Ratio, BigDecimal, and BigInteger literals are currently not supported
- ClojureScript currently only supports integer and floating point literals that map to JavaScript primitives
- Characters
- ClojureScript does not have character literals, instead characters are the same as in JavaScript (i.e. single character strings)
- Symbols and Keywords
- ClojureScript symbols and keywords use the same literal form, but are implemented as JavaScript strings
- Symbols do not currently support the attachment of metadata
- Both can be used as map lookup operators
- Lists, Vectors, Maps, and Set literals are the same as in Clojure
- Macro characters
- Because there are no character nor Var types in ClojureScript neither
\
nor#'
will work
- Because there are no character nor Var types in ClojureScript neither
- Syntax quote ```
- Will still resolve symbols in the current namespace
- Does not support unquote
~
and unquote-splice~@
-
read
- The
read
andread-string
functions are located in thecljs.reader
namespace
- The
- See Quick Start for instructions the ClojureScript REPL.
-
main
support is currently not implemented
- ClojureScript has the same evaluation rules as Clojure
-
load
andload-file
are planned - Runtime
eval
is not supported in ClojureScript
- Vars are not reified at runtime, and the
var
special form is not implemented -
def
produces ordinary JS variables -
monitor-enter
,monitor-exit
, andlocking
are not implemented
The following ClojureScript special forms are identical to their Clojure
cousins: if
, do
, let
, letfn
, quote
, loop
, recur
, throw
, and try
.
-
def
notes- No runtime metadata is placed on vars since there are no vars in ClojureScript
-
:private
metadata is not yet enforced by the compiler
-
if
notes- the section about Java's boolean boxes is irrelevant in ClojureScript
-
var
special form does not exist in ClojureScript -
fn
notes- There is currently no runtime enforcement of arity when calling a fn
- There are currently no pre- and post- conditions on functions
-
monitor-enter
,monitor-exit
, andlocking
are not implemented
Macros are written in Clojure. (See the Lisp differences section above).
- printing
-
*out*
is currently not implemented
-
- regex support
- ClojureScript regular expression support is that of JavaScript
- Numbers
- Currently ClojureScript numbers are just JavaScript numbers
- Coercions are not implemented, since there are currently no types to coerce to
- Characters
- JavaScript has no character type. Clojure characters are represented internally as single-character strings
- Collections
- Persistent collections available
- Ports of Clojure's implementations
- Transient support in place for persistent vectors, hash maps and hash sets
- Most but not all collection fns are implemented
- Persistent collections available
- Seqs have the same semantics as in Clojure, and almost all Seq library functions are available in ClojureScript.
- The
apply
function works but does not correctly handle lazy sequences- More information can be found on ticket #11
-
defprotocol
anddeftype
,extend-type
,extend-protocol
work as in Clojure - Protocols are not reified as in Clojure, there are no runtime protocol objects
- Some reflective capabilities (
satisifies?
) work as in Clojure-
satisfies?
is a macro and must be passed a protocol name
-
-
extend
is not currently implemented
Works as in Clojure, except that there is currently no support for symbol metadata.
- You must currently use the
ns
form only with the following caveats- You must use the
:only
form of:use
- You must use the
:as
form of:require
- The only option for
:refer-clojure
is:exclude
- You must use the
- Macros are written in Clojure, and are referenced via the new
:require-macros
/:use-macros
options to ns- Like
:require
/:use
,:require-macros
and:use-macros
are only supported with:only
/:as
- Like
Existing Clojure libs will have to conform to the ClojureScript subset in order to work in ClojureScript
-
def
andbinding
work as in Clojure- but on ordinary js variables
- Atoms work as in Clojure
- Refs and Agents are not currently implemented
- Validators work as in Clojure
-
doc
andfind-doc
are not currently implemented -
intern
not implemented - no reified Vars
Refs and transactions are not currently supported.
Agents are not currently supported.
Atoms work as in Clojure.
The host language interop features (new
, /
, .
, etc.) work as in Clojure where possible, e.g.:
goog/LOCALE
=> "en"
(let [sb (goog.string.StringBuffer. "hello, ")]
(.append sb "world")
(.toString sb))
=> "hello, world"
To access object properties (including functions that you want as a value, rather than to execute) use a leading hyphen:
(.-Infinity js/window)
=> Infinity
Compilation is different from Clojure:
- All ClojureScript programs are compiled into (optionally optimized) JavaScript.
- Individual files can be compiled into individual JS files for analysis of output
- Production compilation is whole-program compilation via Google Closure compiler
-
gen-class
,gen-interface
, etc. are unnecessary and unimplemented in ClojureScript
ClojureScript currently includes the following non-core namespaces ported from Clojure:
clojure.set
clojure.string
clojure.walk
clojure.zip
-
clojure.core.reducers
-
fold
is currently an alias forreduce
-
ClojureScript is the same (at a Lisp level) as Clojure except for the following:
- no runtime evaluation
- no runtime compilation
Clojure and ClojureScript share the same Contributor Agreement and development process.