In Elixir and in other languages I've had the need to traverse arbitrarily 
nested, complex, tree-like structures, maybe lookup certain things about 
them, transform, filter, and generally just pull them apart. 

Things like processing JSON blobs or other data with with lots of nesting 
and poor definition originating from systems outside of my control are 
pretty common where I work.

In the past I've done this in Elixir with pattern matching and recursion, 
but this can be awkward to model for large structures, and feels slightly 
lower-level than using a function in Enum or Stream that composes better 
with other functions in those modules.

I looked in Elixir to see if there was a function to lazily walk a nested 
Enum depth-first, but couldn't find one, so I'm proposing 
`Stream.traverse/1` (`walk/1` is a good name, too). A few examples of what 
this might look like (newlines added in results for readability):

iex> Stream.traverse([:a, [:b, :c, :d, [:e, :f]]]) |> Enum.to_list
[:a,
 [:b, :c, :d, [:e, :f]],
 :b,
 :c,
 :d,
 [:e, :f],
 :e, 
 :f]


iex> Stream.traverse(%{a: %{b: :c, d: %{e: :f}}})
...> |> Stream.map(fn({k, _v}) -> k end)
...> |> Enum.to_list
[:a, :b, :d, :e]

The function emits elements based on the kind of Enum being walked, so 
lists emit single elements and maps emit `{key, value}` tuples.

The function's behavior should be such that if it is an Enum, it is 
"walkable". ie, any combination of lists and maps should just work, 
regardless of their nesting. Lists can nest in maps, maps can nest in 
lists, etc.

I went ahead and created a patch here, with more examples: 
https://github.com/elixir-lang/elixir/pull/6369

Thanks!


-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/d9be39c3-dbed-4b74-af8c-fee195434358%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to