Proposal: `delete_at/2` and `delete_at/1`

45 views
Skip to first unread message

Myron Marston

unread,
Jul 15, 2016, 4:16:28 PM7/15/16
to elixir-lang-core

Currently, Elixir provides a number of functions that make working with nested data structures very easy and pleasant:

  • get_in/2
  • get_and_update_in/2 and get_and_update_in/3
  • update_in/2 and update_in/3
  • put_in/2 and put_in/3
  • pop_in/1 and pop_in/2

Unfortunately, there’s no similar function for deleting a value from a nested structure. Is its omission intentional? I think a delete_at function would be very useful:

data = %{users: [%{name: "John", age: 27}, %{name: "Betty", age: 40}]}
delete_at(data, [:users, Access.all(), :age])
# => %{users: [%{name: "John"}, %{name: "Betty"}]}

I imagine it would also make sense to provide a delete_at/1 macro that allows the path to be passed using access syntax, just like what put_in/2, pop_in/1, etc provide.

Thoughts?

Myron


José Valim

unread,
Jul 15, 2016, 4:28:49 PM7/15/16
to elixir-l...@googlegroups.com
It is intentional because pop_in does exactly what you want. It deletes and returns the value deleted, which should be straight-forward to discard.


José Valim
Skype: jv.ptec
Founder and Director of R&D

--
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 elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/1d4e99a5-1b9c-4bd6-8313-a55484639a87%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Myron Marston

unread,
Jul 15, 2016, 4:37:27 PM7/15/16
to elixir-lang-core

pop_in works, but it’s not very friendly for pipelines. For example, let’s say I want to do this:

%{users: [%{name: "John", age: 27}, %{name: "Betty", age: 40
}]}
|> delete_at([:users, Access.all(), :age])
|> update_in([:users, Access.all(), :name], &String.downcase/1)
# => %{users: [%{name: "john"}, %{name: "betty"}]}

If pop_in is the only option, I have to break up my pipeline (using an expression like {_, deleted} = pop_in(...) to discard the popped value) or add an elem(1) to my pipeline. IMO, both options make the code far less clear than it would be if delete_at is available.

Also, if the answer is “delete isn’t needed because pop_in exists”, then why do Map and Keyword provide delete and pop operations? The same argument could be made there that delete is unnecessary since they provide pop but I’m glad delete is necessary for them and would like it for nested structures, too.

Myron



--
You received this message because you are subscribed to a topic in the Google Groups "elixir-lang-core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-lang-core/Rw6TLUoNZ0w/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4JUJMKaD3-zLi7_c-wgdFD-hh7LbvHK7y0cXv11Sjkw0w%40mail.gmail.com.

José Valim

unread,
Jul 15, 2016, 5:34:36 PM7/15/16
to elixir-l...@googlegroups.com
You can get the second element of the tuple: 

%{users: [%{name: "John", age: 27}, %{name: "Betty", age: 40}]}
|> pop_in([:users, Access.all(), :age])
|> elem(1)
|> update_in([:users, Access.all(), :name], &String.downcase/1)
# => %{users: [%{name: "john"}, %{name: "betty"}]}

Also, if the answer is “delete isn’t needed because pop_in exists”, then why do Map and Keyword provide delete and pop operations? The same argument could be made there that delete is unnecessary since they provide pop but I’m glad delete is necessary for them and would like it for nested structures, too.

Because adding a function to a module specific to a data-structure can be taken lightly compared to adding yet another function to Kernel.

Myron Marston

unread,
Jul 15, 2016, 5:43:50 PM7/15/16
to elixir-lang-core
Thanks.  I still kinda wish there was `delete_at/2` but I completely understand your reasoning.

--
You received this message because you are subscribed to a topic in the Google Groups "elixir-lang-core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-lang-core/Rw6TLUoNZ0w/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elixir-lang-co...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages