In many applications it becomes necessary to look up a Record, Object or other data structure by a unique identifier, just as a phone book enables one look up a person's phone number by their name. This structure goes by many names: hashtable, lookup table, hashmap, dict, dictionary, map, etc. There are many tools for this in ReasonML, but two good choices are:
Map
from Reason's OCaml standard API.
This is a good general-purpose, performant, immutable dictionary and should probably be
the first choice. Js.Dict.t
.
This is is a thin wrapper over the mutable Javascript object.
It's a good option you are worried about minimizing your bundle size or
are modifying objects that come from JS. If you go to the Reason docs and search
for Map
today, you won't find any resources for Map
. There are many
features in Reason that are supplied by OCaml's standard
library, whose docs are accessible on the API tab of the Reason site,
though certain elements of the standard API are not currently indexed
by the search engine or given much coverage in the standard Reason docs.
If you look in the API tab, you'll find Map - Association tables over ordered types
is one of API entries,
but the API docs can be a little sparse. In cases like this I find it helpful
to search for the item in Real World OCaml book or in Stack Overflow's OCaml posts,
and then use the Reason Tools browser extension
to convert any examples to Reason. See the Links section at the bottom of this post
for more information.
Map
From a List
This example declares a new Record type
called composer
, then constructs a new Map
type with String
instances
as the lookup keys. After we have minted a specialized StringMap
Module,
we create a getComposerMap
function which converts a list
of composer
types
into the StringMap
. See the post on Modules
in Gradus Reason for more info.
/* loading */
This example is powered by:
String
,
the String
module from the Reason OCaml standard API, which is
a Module
that operates on entities of the string
type. List.fold_left
, which is
The Reason equivalent of Javascript's Array.prototype.reduce.
This iterates over an object and accumulates results into another object.
Here, we pass the function that will be applied to each element of the list:
(map, user) => StringMap.add(user.id, user.name, map)
. This function that we supply
itself takes two parameters. The first parameter (here, map
) is the variable
to accumulate results in. The second parameter (here, user
) is the current object
in the iteration:
List.fold_left(
(map, user) => StringMap.add(user.id, user.name, map),
StringMap.empty,
composers
)
This takes the composers
array, which is a list
of composer
types,
and executes the supplied folding function (map, user) => StringMap.add(user.id, user.name, map)
.
For the first composer, map
is StringMap.empty
. For all the other
composers, the map
parameter is the cumulative result of calling
StringMap.add(user.id, user.name, map)
. At the end of fold_left
, the last
composer returns the newly filled StringMap
.
j
string interpolation, which
looks like {j|key:$id, val:$composerName|j}
and is the equivalent of JS' string interpolation. Here, the
$id
and $composerName
variables are resolved from block scope into a string
.module StringMap = Map.Make(String);
, that constructed
a new, specific instance of the Map
Module that has String
map keys.
You could think of Map.Make
as a constructor for a Module, and the
constructed module has the same methods listed in the documentation.Map
Map.Make
Map
sMap
vs Js.Dict.t
List.fold_left
is
the Reason equivalent to JS' Array.reduce.
Here's a Codepen - ES6 + array.reduceImage Credit: Warburton Post Office Boxes by Mick Stanic on Flickr