Smart Maps
Smart maps are a custom map type powered by Pathom resolvers.
With smart maps, you can leverage the power of Pathom processing using the accessible standard Clojure map interfaces.
Using smart maps
To create a smart map, we need the indexes with resolvers, here is a basic example:
When you start a smart map, Pathom creates an atom with the initial data, and then when you request some new information, Pathom triggers the resolver engine, merges the result in the same atom and returns the value for that key, effectively caching it.
This way, the subsequent accesses have the same speed as a local entry.
Nested maps
Nested map values are wrapped with a smart map using the same environment configuration. For example:
important
This only applies to native Clojure/script maps. It doesn't wrap records and other custom map types.
Nested sequences
It also applies for maps inside sequences:
note
Smart maps do the conversion of sequence items to smart maps on the sequence read. This
means that anytime you read a sequence on a smart map, if the sequence is a vector
, that
scan will be done eagerly. Otherwise, it will use map
, and the processing is lazy.
Error modes
By default, if some error happens during the Pathom process, the Smart Map is going
to be silent about it. You can allow the errors to flow up by using the psm/with-error-mode
helper:
The options for error mode are:
::psm/error-mode-silent
(default): Returnnil
as the value, don't throw errors.::psm/error-mode-loud
: Throw the errors on read.
Disable nested wrap
You can disable the automatic nest wrap using (psm/with-wrap-nested? false)
in the env.
Then all values will return as-is.
tip
You can manually wrap nested values in the same way the library does by using the same env on the value, for example:
Preload data
If you know the attributes you will need ahead of time, it's more efficient to load then in a single run than fetching one by one lazily.
You can accomplish this using the fn psm/touch!
, example:
tip
You can also use psm/sm-touch-ast!
to provide an AST directly.
Keys modes
Smart Maps keys mode is a configuration to decide how a smart map respond to (keys smart-map)
To change this, use the helper (psm/with-keys-mode ...)
, these are the available options
for it:
::psm/keys-mode-cached
- the default option,keys
will return the keys cached in the internal smart map atom.::psm/keys-mode-reachable
-keys
will return all possible keys that are reachable from the current data and the index.
danger
Be careful with ::psm/keys-mode-reachable
combined with enabled "nested wrapping".
Considering that, depending on the index and the current data, a simple print
of the
smart map can lead to infinite loops due to smart maps' recursive properties.
Changes to smart maps
You can use the change operations of maps in the smart map (assoc
, dissoc
, ...).
When a change operation happens, you get a new smart map. Be aware this new smart map
doesn't have the cached data from resolvers from the previous one. The modification is
done from the source map
, the one used to create the smart map in the first place.
This is important so any data computed by resolvers can react to the changes based on the new data context. The following example illustrates this behavior:
Inside smart maps
The smart map data structure contains an environment inside of it, there you can find the indexes, the cached data, and any other relevant options that make the setup of the smart map.
You can access the smart map environment using psm/sm-env
. This includes all the data
you sent as env
during the smart map creation, plus the cache atom.
Debugging reads
Sometimes the result will be unexpected, to debug the smart map you can use the psm/sm-get-with-stats
function to return the run stats of the process:
Smart Maps caching
Smart maps use a durable form of the cache by default. The smart maps add the caches at initialization, and they are persisted when variations of that Smart Map are created.
This means, for example, when you assoc
on a Smart Map, the new returned Smart Map still shares the same plan and resolver caches.
Datafy
Smart Maps support the Clojure Datafy / Navigate protocols. This means if you use a REPL visualizer like Reveal or REBL you can navigate the projected data from the Smart Map lazily.
To demonstrate I'll be showing its usage with Reveal in the following video:
Also in REBL: