decasm
Standard library suggested addition
Hi, still pretty new to Elixir. Is there a library equivalent of this? I’ve look but I haven’t found anything that looks right, but I want to make sure before I write a library to do it. It seems pretty general so I just assume it’s eluding me.
# recursive get from collections
defp getr(x, [head|tail]) when is_tuple(x) do
getr(elem(x,head), tail)
end
defp getr(x, [head|tail]) when is_list(x) do
getr(Enum.at(x,head), tail)
end
defp getr(x, [head|tail]) when is_map(x) do
getr(Map.get(x,head), tail)
end
defp getr(x, []) do
x
end
Most Liked
LostKobrakai
This seems like an implementation of get_in/2.
hauleth
The whole get_in/2 and update_in/3 are Elixir version of lenses which is functional structure for handling and manipulating nested structure. In it core functionality these are 2 functions:
-
getwhich extracts data from the structure -
setwhich put data within structure
So get_in/2 can be thought as a list of functions that will extract value from structure in form:
get_in(stuct, [f, g])
# is (roughly) the same as
g(f(struct))
# and
update_in(struct, [f, g], val)
g(f(struct, val), val)
In reality it is “slightly” more complicated as you cannot return “closured object” with multiple functions in Elixir. So instead it works like that:
f =
fn
:get, struct, next -> # extract value and call `next` on it
:update_in, struct, next -> # call next on data and then update `struct`
end
So in the end, example implementation of Access.key!:
def key!(key) do
fn
:get, %{} = data, next ->
# call `next` on extracted data
next.(Map.fetch!(data, key))
:get_and_update, %{} = data, next ->
# get "current data" under key
value = Map.fetch!(data, key)
# call `next` on current value
case next.(value) do
# return value and update structure
{get, update} -> {get, Map.put(data, key, update)}
# remove value from structure
:pop -> {value, Map.delete(data, key)}
end
_op, data, _next ->
raise "Access.key!/1 expected a map/struct, got: #{inspect(data)}"
end
end
peerreynders
Have a look at the Access behaviour.
etc.
iex(1)> users = [{"john", 27}, {"meg", 23}]
[{"john", 27}, {"meg", 23}]
iex(2)> keys = [Access.at(1), Access.elem(0)]
[#Function<1.79554587/3 in Access.at/1>,
#Function<2.79554587/3 in Access.elem/1>]
iex(3)> get_in(users, keys)
"meg"
iex(4)>
peerreynders
Functions also work with
and Access.key/2 can return a default value if the entry is not found.
There’s also Access.filter/1 and Access.all/0.







