Hamt + 1

Hamt+ may not have the same level of recognition or funding as Immutable.js, but we’ve got the better logo. Just look at that friendly Cephalopod of Mutation, bursting onto the immutable landscape all ready to wreck up the place.

Hamt+ v1 is now out, bringing complete API compatibility with Hamt v2.1. This includes support for Javascript iterators and a similar API to ES6’s Map. Compared to regular Hamt, Hamt+ offers support for custom key types, creating maps that use custom hash functions, and, as hinted at above, transient mutation. Transient mutation allows for more efficient batch operations through scoped mutation of the normally immutable data structure.

var hamt = require('hamt_plus');

const book = ["The", "Time", "Traveller", "for", "so", "it", "will", "be", "convenient", "to", "speak", "of", "him", ...];

// Build count of words in `book`
const map = hamt.mutate(map => {
    // The map can be mutated within this block, but these mutations
    // cannot leak outsite of the block.

    // Note how we don't have to assign the value of `map` to the result
    // because `map` is mutated.
    for (let word of book)
        map.modify(word, count => (count || 0) + 1);
}, hamt.empty);

A Hamt+ map can be made mutable at any time, and the mutations are guaranteed not to effect any existing references to the immutable data structure:

const h = hamt.set('a', 1, hamt.make());

const h1 = h.mutate(map => {
    map.set('a', 2);
});

h.get('a') === 1
h1.get('a') === 2

You can also manually scope mutation using beginMutation and endMutation.

const h = hamt.set('a', 1, hamt.make());

const h1 = h.beginMutation();
h1.set('a', 2);
h1.endMutation();

Check out the documentation for the complete API. As mentioned, Hamt+ can be used as a drop in replacement for Hamt. The performance of Hamt+ is slightly worse when dealing only with immutable data structures, but considerably better in cases where transient mutation can be used.

P.S. map.size is now constant time for Hamt+ and regular Hamt too!