• Stars
    star
    203
  • Rank 192,890 (Top 4 %)
  • Language
    Crystal
  • License
    MIT License
  • Created almost 9 years ago
  • Updated over 3 years ago

Reviews

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

Repository Details

Thread-safe, persistent, immutable collections for the Crystal language

Build Status

Immutable

Efficient, thread-safe immutable data structures for Crystal.

Whenever an Immutable data structure is "modified", the original remains unchanged and a modified copy is returned. However, the copy is efficient due to structural sharing. This makes Immutable data structures inherently thread-safe, garbage collector friendly and performant.

At the moment, Immutable implements the following persistent data structures:

  • Immutable::Vector: array-like ordered, integer-indexed collection implementing efficient append, pop, update and lookup operations
  • Immutable::Map: hash-like unordered key-value collection implementing efficient lookup and update operations

Installation

Add this to your application's shard.yml:

dependencies:
  immutable:
    github: lucaong/immutable

Usage

For a list of all classes and methods refer to the API documentation

To use the immutable collections, require immutable in your code:

require "immutable"

Vector (API docs)

# Vector behaves mostly like an Array:
vector = Immutable::Vector[1, 2, 3, 4, 5]  # => Vector [1, 2, 3, 4, 5]
vector[0]                                  # => 1
vector[-1]                                 # => 5
vector.size                                # => 5
vector.each { |elem| puts elem }

# Updating a Vector always returns a modified copy:
vector2 = vector.set(2, 0)                 # => Vector [1, 2, 0, 4, 5]
vector2 = vector2.push(42)                 # => Vector [1, 2, 0, 4, 5, 42]

# The original vector is unchanged:
vector                                     # => Vector [1, 2, 3, 4, 5]

# Bulk updates can be made faster by using `transient`:
vector3 = vector.transient do |v|
  1000.times { |i| v = v.push(i) }
end

Map (API docs)

# Map behaves mostly like a Hash:
map = Immutable::Map[{:a => 1, :b => 2 }]  # => Map {:a => 1, :b => 2}
map[:a]                                  # => 1

# Updating a Map always returns a modified copy:
map2 = map.set(:c, 3)                      # => Map {:a => 1, :b => 2, :c => 3}
map2 = map2.delete(:b)                     # => Map {:a => 1, :c => 3}

# The original map in unchanged:
map                                        # => Map {:a => 1, :b => 2}

# Bulk updates can be made faster by using `transient`:
map3 = Immutable::Map(String, Int32)[]
map3 = map3.transient do |m|
  1000.times { |i| m = m.set(i.to_s, i) }
end

Nested structures

# Nested arrays/hashes can be turned into immutable versions with the `.from`
# method:

nested = Immutable.from({:name => "Ada", :colors => [:blue, :green, :red] })
nested # => Map {:name => "Ada", :colors => Vector [:blue, :green, :red]}

Implementation

Immutable::Vector is implemented as a bit-partitioned vector trie with a block size of 32 bits, that guarantees O(Log32) lookups and updates, which is effectively constant time for practical purposes. Due to tail optimization, appends and pop are O(1) 31 times out of 32, and O(Log32) 1/32 of the times.

Immutable::Map uses a bit-partitioned hash trie with a block size of 32 bits, that also guarantees O(Log32) lookups and updates.

Contributing

  1. Fork it ( https://github.com/lucaong/immutable/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors

  • lucaong Luca Ongaro - creator, maintainer

Acknowledgement

Although not a port, this project takes inspiration from similar libraries and persistent data structure implementations like:

When researching on the topic of persistent data structure implementation, these blog posts have been of great help:

Big thanks to their authors for the great job explaining the internals of these data structures.

More Repositories

1

minisearch

Tiny and powerful JavaScript full-text search engine for browser and Node
TypeScript
4,701
star
2

jQCloud

jQuery plugin for drawing neat word clouds that actually look like clouds
JavaScript
646
star
3

cubdb

Elixir embedded key/value database
Elixir
555
star
4

guitarstack

Digital guitar effects right in your browser!
JavaScript
200
star
5

react-minisearch

React integration for the MiniSearch client side full-text search library
TypeScript
46
star
6

jquery-machine

Kick-ass finite state machines with jQuery
JavaScript
41
star
7

nerves_thermal_camera

Thermal camera imaging with Elixir, Nerves, Raspberry Pi, and a MLX90640 sensor
Elixir
37
star
8

noiseGen

A jQuery plugin to generate background noise dynamically
JavaScript
31
star
9

cubq

Queue and stack semantics on top of CubDB
Elixir
23
star
10

elixir_bme680

An Elixir library to interface with the BME680 (and BME280) environmental sensor
C
19
star
11

sprockets-chain

Pure JS dependency chain generator for Sprockets
JavaScript
13
star
12

similaria

Scala library implementing a performant and easy to use item-based recommendation engine
Scala
12
star
13

elixir_mlx90640

An Elixir library to interface with the MLX90640 Far Infrared Thermal Sensor Array.
C++
11
star
14

meteor-omnipoll

Quick polls with Meteor
JavaScript
10
star
15

jsterminal

JSterminal, one bookmarklet to rule 'em all
JavaScript
9
star
16

chitchat

An educational object oriented toy language
JavaScript
8
star
17

ablab

Minimal AB-test library for Rails applications
Ruby
7
star
18

submachine

Kick-ass JavaScript finite state machines
CoffeeScript
7
star
19

nerves_rpi4_hid_gadget_poc

Proof of concept of enabling USB-C gadget mode on Raspberry Pi 4 with Nerves
Elixir
6
star
20

Moka

a damn cool static website framework
Ruby
5
star
21

Vimfiles

My messy .vim folder
Vim Script
5
star
22

risp

LISP interpreter in Ruby with macros and interop, because why not?
Ruby
5
star
23

jquery-toCurrency

jQuery plugin to format numbers to currency
JavaScript
5
star
24

wheels-class

Simple and powerful classical inheritance for JavaScript. Fully compatible with CommonJS / Node, AMD and standard browser script tag include.
JavaScript
3
star
25

gwooks

A DSL for quickly creating endpoints for GitHub post-receive webhooks
Ruby
3
star
26

eventspitter

Minimal but versatile JavaScript pub/sub working everywhere
CoffeeScript
3
star
27

dataspec

Describe how your data should look like, validate it and generate examples
JavaScript
2
star
28

loud-accessors

JavaScript attribute accessors (getter and setter) that emit events on change and read
CoffeeScript
2
star
29

miniprofiler-dashboard

A nice UI and dashboard for MiniProfiler
JavaScript
2
star
30

wheels-pubsub

Simple and lightweight PubSub, fully compatible with CommonJS / Node, AMD and standard browser script tag include.
JavaScript
2
star
31

TwitterSimulationModel

An agent-based simulation model of Twitter network
Java
1
star
32

old_lucaongaro.eu

My old personal website
Ruby
1
star
33

lucaongaro.eu

My personal website and blog
CSS
1
star
34

share-experiment

An experiment
JavaScript
1
star
35

pantiltcam

WebRTC controlled pan-tilt night vision camera experiment
HTML
1
star