bitwalker/toml-elixir

Transforms should provide list as a first argument

hauleth opened this issue · 2 comments

This would allow to parse nested structures more easily. IMHO the best way would be to provide list from most nested value to least nested one, so for file:

[foo]
bar = { baz = 1 }

The transformer argument would look like [:baz, :bar, :foo]. This would simplify migration, as current

def transform(:baz, value), do: value

would look like:

def transform([:baz | _], value), do: value

I think maybe I need an example of the problem this is intended to solve, as your current example shows how the arguments look when transforming the same key, but not what you want to be able to do with the new form versus the old.

Sometimes it makes sense to wait until you get the value for :foo before trying to transform the children, perhaps because the context of :foo determines how the child keys are transformed, but when sketching out the API, I couldn't think of any examples where having the key path is any more useful than waiting for the transforms to reach higher up in the tree (i.e. :foo rather than :bar).

I will readily admit though that I have not thought of all use cases, so a good example of where the current API falls apart would be very helpful in figuring out a better approach - I'm just not convinced that passing the key path instead is the right way. If more metadata about keys is needed, we might instead want to pass a more opaque context object, that allows us to store a variety of metadata information about each key and it's surrounding context as the document is being transformed.

Perhaps another approach if the current API is insufficient, is to simply map keys/keypaths to a transformer, which is then applied when that key is reached. It is more explicit, and thus more verbose, but has the benefit of being precise.

Thoughts?

One problem I can see with the current approach is if you have the same key appear in multiple contexts.

for example:

[my_app]
things = ["foo", "bar"]

[some_dep]
things = ["x", "y", "z"]

Now say I want to transform my_app.things into a struct. I don't have enough context to know which one I'm looking at. The workaround for now is to match the my_app key instead and transform the nested value, but I think the proposed solution would be easier to work with.