Erlang Central

Hash with Immutable Keys or Values

From ErlangCentral Wiki


You would like to have a hash table whose values or keys couldn't be modified once set.


The provided hash-table-like modules don't offer immutability. If you really want this, however, you can always use your own interface to the data structure, which checks to make sure that you don't change anything you don't want changed. This interface might also ensure that only certain types of data are written, or log elsewhere what data is written, and so on.

Here is a silly example of an 'immutable hash' library, in the form of a process that prevents double-puts into its process dictionary. A real implementation would depend on real needs.

-export([new/0, loop/0, set/3, lookup/2]).

new() -> spawn(?MODULE, loop, []).

loop() ->
        M={Pid,set,K,V} ->
            case get(K) of
                undefined -> put(K,V),
                             Pid ! {self(),ok,M},
                _ -> Pid ! {self(),already_defined,M},
        M={Pid,lookup,K} -> Pid ! {self(),get(K),M},

lookup(Hash,K) ->
    Hash ! M={self(),lookup,K},
    receive {Hash,Res,M} -> Res end.

set(Hash,K,V) ->
    Hash ! M={self(),set,K,V},
        {Hash,ok,M} -> ok;
        {Hash,already_defined,M} -> {error,already_defined}

Sample usage:

1> H = immutable_hash:new().
2> immutable_hash:set(H,test,5).
2> immutable_hash:set(H,test,6).
3> immutable_hash:lookup(H,test).


In some ways, Erlang dict Dictionaries are immutable by design. Each time you insert a value into a dictionary, it creates a brand new dictionary containing the data from the old dictionary, plus the newly inserted entry.

If you wish to have a read-only dictionary, you can structure your program so that the dict term is passed into functions for use, but that you never receive a new dictionary value from another function. In this way, the single-assignment nature of Erlang guarantees that the dictionary is unchanged.

ets tables are more problematic, because the permit updates to the table by name, and Erlang's single-assignment behavior does not provide any protection here.

This seems to be an area where Erlang can only provide this functionality if the programmer uses the single-assignment nature of the language to proper use.