Suppose I have a Network struct that contains a map from names to Clusters, and a Cluster contains a MapSet of “downstream” names:
I can easily use update_in
to work with one of the clusters:
path = [Access.key(:name_to_cluster), :b, Access.key(:downstream)]
update_in(network, path, &MapSet.put(&1, :cluster_name))
But what if I want to add a downstream to N clusters? I was suspecting that Access.all
would “explode” the map into a list of {key, value}
tuples, like what for {k,v} <- a_map ...
does. But alas:
** (RuntimeError) Access.all/0 expected a list
So, to use Access
, do I have to reduce
over the N names?
clusters_to_update = [:gate, :watcher]
Enum.reduce(clusters_to_update, network, fn elt, acc ->
path = [Access.key(:name_to_cluster), elt, Access.key(:downstream)]
update_in(acc, path, &MapSet.put(&1, :cluster_name))
# or...
# update_in(acc.name_to_cluster[elt].downstream, &MapSet.put(&1, :cluster_name))
end)
That’s better than having to assemble each level on the way “out” of the descent (though my 1981 self, programming in C on a computer with 64K of memory, screams at the N^2 space cost), but is it the best I can do, short of a Lens
package?
If so, I’m curious why Access.all
is restricted to List, rather than open to all Enums? (1981 Brian cries, “do you know what indirecting through a function pointer costs?”)
P.S. I’m also curious why my posts are always marked private? I don’t see anything in the compose window to change that, I never consciously chose it, I don’t see anything in my preferences, and I can’t find anything in the Discord documentation to explain it.