An implementation of the confluently persistent vector data structure introduced in Bagwell, Rompf, "RRB-Trees: Efficient Immutable Vectors", EPFL-REPORT-169879, September, 2011.
RRB-Trees build upon Clojure's PersistentVectors, adding logarithmic
time concatenation and slicing. ClojureScript is supported with the
same API except for the absence of the vector-of
function.
The main API entry points are clojure.core.rrb-vector/catvec
,
performing vector concatenation, and clojure.core.rrb-vector/subvec
,
which produces a new vector containing the appropriate subrange of the
input vector (in contrast to clojure.core/subvec
, which returns a
view on the input vector).
core.rrb-vector's vectors can store objects or unboxed primitives. The
implementation allows for seamless interoperability with
clojure.lang.PersistentVector
, clojure.core.Vec
(more commonly
known as gvec) and clojure.lang.APersistentVector$SubVector
instances: clojure.core.rrb-vector/catvec
and
clojure.core.rrb-vector/subvec
convert their inputs to
clojure.core.rrb_vector.rrbt.Vector
instances whenever necessary
(this is a very fast constant time operation for PersistentVector and
gvec; for SubVector it is O(log n), where n is the size of the
underlying vector).
clojure.core.rrb-vector
also exports its own versions of vector
,
vector-of
and vec
which always produce
clojure.core.rrb_vector.rrbt.Vector
instances. Note that vector-of
accepts :object
as one of the possible type arguments, in addition
to keywords naming primitive types.
core.rrb-vector exports one public namespace:
(require '[clojure.core.rrb-vector :as fv])
Note that the ClojureScript version uses the same namespace name (it
does not use the alternative cljs.*
prefix!). This is because the
API is precisely the same (except clojure.core.rrb-vector/vector-of
only makes sense on the JVM and is therefore not available in
ClojureScript).
The docstring attached to the namespace provides an overview of the available functionality (as found at the top of this README):
(doc clojure.core.rrb-vector)
The new functionality is accessible through two functions:
clojure.core.rrb-vector/subvec
, which provides logarithmic-time
non-view slicing (in contrast to clojure.core/subvec
, which is a
constant-time operation producing view vectors that prevent the
underlying vector from becoming eligible for garbage collection), and
clojure.core.rrb-vector/catvec
, which provides logarithmic-time
concatenation. Crucially, these can be applied to regular
Clojure(Script) vectors.
(doc fv/subvec)
(doc fv/catvec)
;; apply catvec and subvec to regular Clojure(Script) vectors
(fv/catvec (vec (range 1234)) (vec (range 8765)))
(fv/subvec (vec (range 1024)) 123 456)
Additionally, several functions for constructing RRB vectors are
provided. There is rarely any reason to use them, since, as mentioned
above, the interesting functions exported by core.rrb-vector work with
regular vectors. Note that clojure.core.rrb-vector/vec
, in contrast
to clojure.core/vec
, reuses the internal tree of its input if it
already is a vector (of any type) and does not alias short arrays.
When passed a non-vector argument, it returns an RRB vector.
(doc fv/vector)
(doc fv/vector-of)
(doc fv/vec)
The debug namespace bundled with core.rrb-vector provides several utilities used by the test suite, as well as a function for visualizing the internal structure of vectors that works with regular Clojure(Script) vectors and RRB vectors.
;; for peeking under the hood
(require '[clojure.core.rrb-vector.debug :as dv])
(dv/dbg-vec (fv/catvec (vec (range 1234)) (vec (range 8765))))
more tests;
benchmarks;
performance: general perf tuning, more efficient catvec
implementation (to replace current seq-ops-based impl).
core.rrb-vector requires Clojure >= 1.5.0. View vectors created by
clojure.core/subvec
are correctly handled for Clojure >= 1.6.0. The
ClojureScript version is regularly tested against the most recent
ClojureScript release.
core.rrb-vector releases are available from Maven Central. Development snapshots are available from the Sonatype OSS repository.
Follow the first link above to discover the current release number.
Leiningen dependency information:
[org.clojure/core.rrb-vector "${version}"]
Maven dependency information:
<dependency>
<groupId>org.clojure</groupId>
<artifactId>core.rrb-vector</artifactId>
<version>${version}</version>
</dependency>
Gradle dependency information:
compile "org.clojure:core.rrb-vector:${version}"
core.rrb-vector is being developed as a Clojure Contrib project, see the What is Clojure Contrib page for details. Patches will only be accepted from developers who have signed the Clojure Contributor Agreement.
To run Clojure and ClojureScript tests:
$ mvn -DCLOJURE_VERSION=1.10.1 -Dclojure.version=1.10.1 clean test
Clojure versions as old as 1.5.1 can be tested with such a command, but the ClojureScript tests only work when using Clojure 1.8.0 or later.
To run tests and, if successful, create a JAR file in the targets directory:
$ mvn -DCLOJURE_VERSION=1.10.1 -Dclojure.version=1.10.1 clean package
Prerequisites: Only Java and Maven need to be installed. Maven will download whatever versions of Clojure are needed for the command you use. Both Clojure and ClojureScript tests are run with the commands given here. They use the Nashorn JavaScript run time environment included with Java -- no other JavaScript run time is needed.
To run relatively short Clojure tests, but no ClojureScript tests:
$ ./script/jdo test
To run relatively short ClojureScript tests, but no Clojure tests:
$ ./script/sdo test
Replace test
in the commands above with one of the following for
other useful things:
sock
(or no argument at all) - start a REPL, and listen for a
socket REPL connection on TCP port 50505long
- run a longer set of testscoll
- run generative tests from
collection-check
libraryeast
- run Eastwood lint tool (clj version only, not cljs)To run Clojure tests, but no ClojureScript tests:
$ lein with-profile +1.10 test
You can test with Clojure versions 1.5 through 1.10 by specifying that
version number after the +
.
Prerequisites: Only Java and Leiningen. Leiningen will download whatever versions of Clojure and other libraries are needed.
To run ClojureScript tests with Node.js and SpiderMonkey JavaScript runtimes, but no Clojure tests:
$ lein with-profile +cljs cljsbuild test
Add node
or spidermonkey
as a separate argument after test
to
restrict the JavaScript runtime used to only the one you specify. You
may need to adjust the command names in the :test-commands
section
of the project.clj
file if the command for running those JavaScript
runtimes have a different name on your system than what is used there.
Prerequisites: Java, Leiningen, and either or both of Node.js and SpiderMonkey JavaScript run time environments.
To run normal Clojure tests, plus the
collection-check
tests, but no ClojureScript tests:
$ lein with-profile +coll,+1.7 test
The collection-check
tests require Clojure 1.7.0 or later, I believe
because collection-check and/or its dependencies require that.
There is no existing command configured to run collection-check
tests with ClojureScript.
To start a REPL from Leiningen with Clojure versions 1.6.0 and older, you must use Leiningen 2.8.0 (likely some other versions work, too).
For all of the development commands you must have Java installed. This includes the ClojureScript compile and test commands, since the ClojureScript compiler is at least partially written in the Java version of Clojure.
Install one or more of the pre-built binaries from AdoptOpenJDK, or several other providers of Java binaries.
Additional methods:
sudo apt-get install default-jre
For any mvn
command you must install
Maven.
sudo apt-get install maven
brew install maven
sudo port install maven3
, then either use the
command mvn3
, or to use mvn
also run the command sudo port select --set maven maven3
.An install script and instructions are available on the Leiningen site.
Installation instructions for many different versions of Node.js are available on the Node.js web site. You can also install it using the commands below.
sudo apt-get install nodejs
brew install node
sudo port install nodejs10
. You can see other
versions available via the command port list | grep nodejs
.Installation instructions for many different versions of SpiderMonkey are available on the SpiderMonkey web site. You may also install it using the commands below.
sudo apt-get install libmozjs-52-dev
brew install spidermonkey
installs version 1.8.5 of SpiderMonkey, which according to the
Wikipedia page on SpiderMonkey was first released in 2011, with at
least one release per year after that. The ClojureScript tests
fail to run using this version of SpiderMonkey. It seems worth
avoiding this version of SpiderMonkey for the purposes of testing
core.rrb-vector
.sudo port install mozjs52
core.rrb-vector's vectors support the same basic functionality regular Clojure's vectors do (with the omissions listed above). Where possible, this is achieved by reusing code from Clojure's gvec and ClojureScript's PersistentVector implementations. The Clojure(Script) source files containing the relevant code carry the following copyright notice:
Copyright (c) Rich Hickey. All rights reserved.
The use and distribution terms for this software are covered by the
Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
which can be found in the file epl-v10.html at the root of this distribution.
By using this software in any fashion, you are agreeing to be bound by
the terms of this license.
You must not remove this notice, or any other, from this software.
Copyright © 2012-2019 Michał Marczyk, Andy Fingerhut, Rich Hickey and contributors
Distributed under the
Eclipse Public License 1.0,
the same as Clojure. The licence text can be found in the
epl-v10.html
file at the root of this distribution.
Can you improve this documentation? These fine people already did:
Michał Marczyk & Andy FingerhutEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close