Skip to content

Differences from Clojure

jimt edited this page Jul 21, 2011 · 40 revisions

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.

Rationale

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.

State and Identity

Same as Clojure. Clojure's identity model is simpler and more robust than mutable state, even in single threaded environments.

Dynamic Development

ClojureScript's REPL can be launched from within the Clojure REPL. See Quick Start for details.

Functional Programming

ClojureScript has the same immutable collections, but the alpha versions are not necessarily persistent. Persistent versions will be added over time.

Lisp

ClojureScript's macros are written in Clojure, and are referenced via the refer-macros keyword in namespace declarations:

(ns my.namespace
  (:refer-macros '[my.macros :as my])

The :as prefix selector is required in :refer-macros. One point of note is that the code generated by ClojureScript macros must target the capabilities in ClojureScript.

Runtime Polymorphism

  • ClojureScript protocols have the same semantics as Clojure protocols.
  • Multimethods are currently not yet implemented nor are hierarchies

Concurrent Programming

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
  • Agents are currently not implemented

Hosted on the JVM

Getting Started

See Quick Start

The Reader

  • Numbers
    • ClojureScript currently only supports integer and floating point literals that map to JavaScript primitives
      • Ratio, BigDecimal, and BigInteger literals are currently not supported
  • 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
    • ClojureScript does not currently support regular expression literals using #""
  • Syntax quote ```
    • Will still resolve symbols in the current namespace
    • Does not support unquote ~ and unquote-splice ~@
  • read
    • The read and read-string functions are located in the cljs.reader namespace

The REPL and main

  • See Quick Start for instructions the ClojureScript REPL.
  • main support is currently not implemented

Evaluation

  • ClojureScript has the same evaluation rules as Clojure
  • load and load-file are planned
  • Runtime eval is not supported in ClojureScript

Special Forms

  • Vars are not reified at runtime, and the var special form is not implemented
  • def produces ordinary JS variables
  • monitor-enter, monitor-exit, and locking are not implemented

Special Forms

The following ClojureScript special forms are identical to their Clojure cousins: if, do, let, 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, and locking are not implemented

Macros

Macros are written in Clojure. (See the Lisp differences section above).

Other Functions

Data Structures

  • Numbers
    • Currently ClojureScript numbers are just JavaScript numbers
  • Coercions are not implemented, since there are no currently types to coerce to
  • Characters
    • JavaScript has no character type. Clojure characters are represented internally as single-character strings
  • Collections
    • In the first release, some immutable collections are copy-on-write are not persistent
  • Most but not all collection fns are implemented

Seqs

  • 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

Transients

Transients are not currently implemented

Multimethods

Multimethods are not currently implemented

Protocols

  • defprotocol and deftype, 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
  • defrecord, reify, and extend are not currently implemented

Metadata

Works as in Clojure, except that there is currently no support for symbol metadata.

Namespaces

  • You must currently use the ns form only with the following caveats
    • :use is not supported
    • You must use the :as form of :require
    • The only option for :refer-clojure is :exclude
  • Macros are written in Clojure, and are referenced via the new :require-macros option to ns

Libs

Existing Clojure libs will have to conform to the ClojureScript subset in order to work in ClojureScript

Vars and the Global Environment

  • def and binding 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 and find-doc are not currently implemented

Refs and Transactions

Refs and tranasactions are not currently supported.

Agents

Agents are not currently supported.

Atoms

Atoms work as in Clojure.

Host Interop

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")
 (. sb (toString)))
=> "hello, world"

The one important difference is in calling no-argument methods. In Java (. x toString), where toString is a method, would unambiguously mean "call the toString method of x". JavaScript is more flexible, separating "method" lookup from invocation. So in ClojureScript you have to make a choice:

(. sb toString)     => returns a function
(. sb (toString))   => calls the function

Note the latter form is supported in standard Clojure, but rarely used.

Compilation and Class Generation

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

Other Libraries

ClojureScript currently includes the following non-core namespaces ported from Clojure:

  • clojure.set
  • clojure.string
  • clojure.walk
  • clojure.zip

Differences with other Lisps

ClojureScript is the same (at a Lisp level) as Clojure except for the following:

  • no runtime evaluation
  • no runtime compilation
  • letfn is not currently implemented

Contributing

Clojure and ClojureScript share the same Contributor Agreement and development process.

Clone this wiki locally