• Stars
    star
    3,389
  • Rank 12,603 (Top 0.3 %)
  • Language
    Clojure
  • Created almost 12 years ago
  • Updated about 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

ClojureScript's persistent data structures and supporting API from the comfort of vanilla JavaScript

mori

Mori

A simple bridge to ClojureScript's persistent data structures and supporting APIs for vanilla JavaScript. Pull requests welcome.

Breaking changes in 0.3.0

The API now uses idiomatic JavaScript naming conventions.

Improvements to 0.3.0

Faster

Mori is considerably faster across the board thanks to recent enhancements to the ClojureScript compiler. For users who would like to benchmark their immutable data structure implementations against Mori, Mori now exposes direct arity invokes which eliminates previous calling overheads from arity dispatching. See Benchmarking for more information.

Mori hash maps now default to ClojureScript ArrayMaps that are automatically promoted to PersistentHashMaps as needed. ArrayMaps deliver considerably better performance at small sizes and when simple keys are at play. For example a Mori hash map with less than or equal to eight keys can now be built nearly an order of magnitude faster than Immutable.js 3.6.2 Maps.

More ES6

All Mori collections support ES6 iteration via foo[Symbol.iterator] or foo["@@iterator"].

Differences from Immutable.js

  • A functional API, data structures do not have public methods
  • Faster, ClojureScript data structures have been subjected to more real world usage and continuous benchmarking for nearly 4 years
  • Larger, gzipped the base Mori module is about 6K larger than Immutable.js

Getting it

You can install the latest release via npm:

npm install mori

The installed package contains a single optimized JavaScript file mori.js.

Load mori in your Node.js programs as you would any other module:

var mori = require("mori");

In a browser, you can load mori with a script tag, as you would any other JavaScript library:

<script src="mori.js" type="text/javascript"></script>

You can also load it as an AMD module, e.g. with RequireJS.

Usage

You can use it from your projects like so:

var inc = function(n) {
  return n+1;
};

mori.intoArray(mori.map(inc, mori.vector(1,2,3,4,5)));
// => [2,3,4,5,6]

Efficient non-destructive updates!

var v1 = mori.vector(1,2,3);
var v2 = mori.conj(v1, 4);
v1.toString(); // => '[1 2 3]'
v2.toString(); // => '[1 2 3 4]'
var sum = function(a, b) {
  return a + b;
};
mori.reduce(sum, mori.vector(1, 2, 3, 4)); // => 10

Lazy sequences!

var _ = mori;
_.intoArray(_.interpose("foo", _.vector(1, 2, 3, 4)));
// => [1, "foo", 2, "foo", 3, "foo", 4]

Or if it's more your speed, use it from CoffeeScript!

inc = (x) -> x+1  
r = mori.map inc, mori.vector(1,2,3,4,5)
mori.intoArray r

Documentation

You can find extensive documentation and examples here.

More Examples

Efficient Freeze/Thaw

For vectors and maps we provide an efficient thaw and freeze operations:

var m = mori;

// ~220ms with V8 version 3.29.80 MBP 2.26ghz
for(var j = 0; j < 10; j++) {
  var s = new Date();
  var arr = [];
  for(var i = 0; i < 10000000; i++) {
    arr.push(i);
  }
  print("Array push " + arr.length + " items " + ((new Date())-s));
  gc();
}

// ~70ms
for(var j = 0; j < 10; j++) {
  s = new Date();
  var mv = m._thaw(m.vector());
  for(var i = 0; i < 10000000; i++) {
    mv = m._conj.f2(mv, i);
  }
  var v = m._freeze(mv);
  print("Mutable vector conj " + m.count(v) + " items " + ((new Date())-s));
  gc();
}

ES6 Map/Set inspired interfaces

All Mori maps and sets support all the non-mutating methods of the proposed ES6 Map and Set interfaces. The main difference with the spec is that key lookup is based on value not reference. keys, values, and entries methods return the proposed mutable iterators:

var m = mori;
var h = m.hashMap("foo", 1, "bar", 2);

h.has("foo"); // => true
h.get("foo"); // => 1

var iter = h.keys();
iter.next(); // => {done: false, value: "foo"}

This feature is subject to changes in the ES6 proposal.

Transducers

Mori includes Transducers. Zero allocation collection operations FTW:

var m = mori;
var a = [];

for(var i = 0; i < 1000000; i++) {
  a.push(i);
}

// make it immutable
var v = m.into(m.vector(), a);

function time(f) {
  var s = new Date();
  f();
  console.log(((new Date())-s)+"ms");
}

// ~190ms V8 version 3.29.80 MBP 2.26ghz
time(function() {
  var xf = m.comp(m.map(m.inc), m.map(m.inc), m.map(m.inc));
  return m.transduce(xf, m.completing(m.sum), 0, v);
}, 10);

// ~440ms
time(function() {
  return a.map(m.inc).map(m.inc).map(m.inc).reduce(function(a,b){return a+b;}, 0);
}, 10);

Build

Prerequisites

You will first need to install the Java SDK, if it's not already installed on your system.

On Windows, you will need to manually install Leiningen. On UNIX-like systems, Leiningen will be installed within the project automatically if the lein executable is not found on your path or if your lein version predates 2.0.0.

Clone the repo

git clone https://github.com/swannodette/mori.git
cd mori

On a UNIX-like system build with

./scripts/build.sh

Alternatively using npm

npm run-script build

On Windows

./scripts/build.ps1

The build process will generate an optimized JavaScript file mori.js, which is suitable for use with Node.js, or in a Web browser or other JavaScript environments. You can also load it as an AMD module.

Copyright (C) 2012-2015 David Nolen and contributors

Distributed under the Eclipse Public License, the same as Clojure.

More Repositories

1

logic-tutorial

A Very Gentle Introduction to Relational Programming
Clojure
935
star
2

lt-cljs-tutorial

A ClojureScript Programming Language Tutorial for Light Table Users
Clojure
864
star
3

enlive-tutorial

An Easy Introduction to Enlive
Clojure
612
star
4

mies

Minimal ClojureScript project template
Clojure
371
star
5

delimc

Delimited continuations for Clojure
Clojure
207
star
6

hello-cljsc

Hello ClojureScript Compiler
Clojure
192
star
7

om-sync

A reusable Om component for keeping local application state in sync with server application state
Clojure
168
star
8

cljs-bootstrap

ClojureScript compiling ClojureScript
Clojure
162
star
9

om-next-demo

TodoMVC with Om Next
Clojure
137
star
10

mies-node-template

A minimal ClojureScript Node.js template
Clojure
116
star
11

async-tests

Having fun with core.async
Clojure
104
star
12

swannodette.github.com

Clojure
80
star
13

clojure-snippets

Yasnippet's for Clojure
79
star
14

chambered

Port of Notch's Minecraft JavaScript demo to ClojureScript
Clojure
69
star
15

mies-om

Less is More template for Om
Clojure
53
star
16

jsx-fun

Experiments in transforming from React Native JSX/Flow into Closure Modules
JavaScript
30
star
17

clj-nehe

Nehe Tutorials in Clojure using Penumbra
Clojure
29
star
18

ejecta-cljs-template

ClojureScript + Ambly + Ejecta
Objective-C
29
star
19

native-deps

Native dependencies plugin for Leiningen
Clojure
29
star
20

react-cljs

Facebook React package for deployment to Clojars
JavaScript
28
star
21

om-datascript

Om Next w/ DataScript
Clojure
26
star
22

transit-example

A basic Transit example for Clojure/ClojureScript users
Clojure
21
star
23

om-async-tut

Template for Om Asyn Application State tutorial
Clojure
21
star
24

fun.coffee

Putting the funk into your coffee
CoffeeScript
19
star
25

cljs-master

ClojureScript Master Class
Clojure
17
star
26

transit-js-example

A transit-js example
JavaScript
17
star
27

cljs-demo

Demo repo for BK.js and NYC.js
JavaScript
16
star
28

hs-async

Examples for Tuesday
Clojure
15
star
29

om-nashorn

Om example that you can run with Nashorn
Clojure
14
star
30

GistPad

Gists for the iPad
Objective-C
12
star
31

cljs-ess

ClojureScript Essentials
Clojure
12
star
32

sicp

Chapters 4 and 5 of SICP
Scheme
11
star
33

ob-sml

org-babel support for Standard ML
Emacs Lisp
10
star
34

Vector2D

Basic fast 2D vector math for Objective-C
Objective-C
9
star
35

paip

Paradigms of Artificial Intelligence
Common Lisp
9
star
36

littlecomputers

Source code files for the ITP Little Computers class
Objective-C
8
star
37

es6-demo

ES6 support demo
Clojure
8
star
38

worlds

Worlds management for Om
Clojure
8
star
39

flocking

Dan Shiffman's flocking code ported to Clojure
Clojure
7
star
40

hs-compilers

Compilers Made Easy talk
Clojure
6
star
41

minikanren

My study of miniKanren in Racket
Scheme
6
star
42

sol

Python based library for talking to HPGL pen plotters
Python
5
star
43

underoop

Classes and Modules for Underscore.js
JavaScript
5
star
44

ui-check

Playground for testing transaction event generation for automated UI testing
Clojure
5
star
45

baduk

My Go/Weiqi/Baduk Blog
SCSS
5
star
46

ArtAndCode

Repository for Art && Code mobile iPhone workshop
Objective-C
4
star
47

fairKanren

miniKanren with fair conjunction
Scheme
4
star
48

cocoahelpers

some helpers for Cocoa programming
4
star
49

nyt-gen-talk

Code for the NYT ES6 Generators talk tomorrow
JavaScript
3
star
50

django-bbcode

a git fork of http://bitbucket.org/ojii/django-bbcode/
Python
3
star
51

alphaKanren

Understanding the alphaKanren implementation
Scheme
3
star
52

lt-settings

My Light Table Settings
2
star
53

js-snippets

JavaScript yasnippets
2
star
54

cljs-material

Using NPM Material from CLJS
Clojure
2
star
55

promisejs

Future and promises for server and client-side JavaScript
1
star
56

cljs-stl

Code for Strange Loop
Clojure
1
star
57

cljs-no-ns-test

Clojure
1
star
58

jampack

Useful instruments for Om
1
star
59

om-weasel-repro

Clojure
1
star
60

convex-hull

Optimized version of Uncle Bob's code
Clojure
1
star
61

techmesh-logic

TechMesh Conference Logic Demo Code
Clojure
1
star
62

techmesh-cljs

TechMesh Conference ClojureScript Demo Code
Clojure
1
star
63

zrch-logic

Logic Programming examples from Zurich Clojure Meetup
Clojure
1
star