[Proposal] Add `List.pop/2`

72 views
Skip to first unread message

h...@nathanmlong.com

unread,
Mar 4, 2022, 9:45:47 AM3/4/22
to elixir-lang-core
This is a modified version of what I proposed in https://github.com/elixir-lang/elixir/pull/11681

Similar to `Map.pop/2` and and `Keyword.pop/2`, I propose adding `List.pop/2`.

I also propose adding `List.find_and_pop/2`, which is more generalized since it takes a function.

Here are possible implementations.

```elixir
@doc """
Returns and removes the first value matching `item` in the `list`.

## Examples
   iex> List.pop([1, 2, 2, 3], 2)
   {2, [1, 2, 3]}
   iex> List.pop([1, 2, 3, 4], 20)
   {nil, [1, 2, 3, 4]}
"""
def pop(list, item) do
  find_and_pop(list, &(&1 == item))
end

@doc """
Returns and removes the first value matching `fun` in the `list`.

## Examples
   iex> List.find_and_pop([1, 2, 3, 4], &(&1 > 2))
   {3, [1, 2, 4]}
   iex> List.find_and_pop([1, 2, 3, 4], &(&1 > 20))
   {nil, [1, 2, 3, 4]}
"""
def find_and_pop(list, fun) do
  case Enum.find_index(list, fun) do
    nil -> {nil, list}
    i -> pop_at(list, i)
  end
end
```

José Valim

unread,
Mar 4, 2022, 11:05:35 AM3/4/22
to elixir-lang-core
Hi Nathan, thanks for the email. Can you please show some examples of where they could be handy with some context around them? Thank you!

--
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/bdc98b8c-fc73-40d7-8287-eb0b5d3ea97en%40googlegroups.com.

h...@nathanmlong.com

unread,
Mar 7, 2022, 10:51:49 AM3/7/22
to elixir-lang-core
Hmm. I can't give too much detail, but the basic context is a LiveView form where the user selects some ports and the form provides suggestions as they type. Eg, if they type `2` it will suggest `22 - SSH`, `25 - SMTP`, etc.

The currently-selected ports are a list of integers. If `22` is already selected, the LiveView won't suggest it. So if the LiveView gets a message to deselect `22`, it tries to pop it out of the `selections` list. If the pop succeeds, the `suggestions` list can be updated to include port `22` again. If the pop doesn't succeed, we can ignore the message; we can't deselect a port that wasn't selected to start with.

I can't combine `selected` and `suggested` (eg by flagging the suggestions which are also selected) because both collections can contain elements that the other doesn't contain; the user may select ports that are not in the suggestions list. And it's not practical to have a top-level list of every possible port and flag each as `selected`, `suggested`, or both, because there are are 65,535 possible ports.

So the core of my use case is: I get a user message to remove an item from a list, and after attempting to remove it, I want to take a follow-up action only if the item was was actually in the list.

Max Veytsman

unread,
Mar 7, 2022, 11:49:06 AM3/7/22
to elixir-l...@googlegroups.com
For what it's worth, I use MapSets for these kinds of autocompletion suggestion lists in LiveView. It's worth noting that these aren't guaranteed to preserve insertion order, and I'm relying on a implementation detail that they will for a small number of keys.

Ben Wilson

unread,
Mar 8, 2022, 9:22:32 AM3/8/22
to elixir-lang-core
I would benchmark to make sure that you're actually gaining something. If you are relying on it to be small, then at that specific size a list might also just be fine, and you won't be relying on behavior that could change in a future release.

Max Veytsman

unread,
Mar 8, 2022, 9:42:53 AM3/8/22
to elixir-l...@googlegroups.com
Oh I completely agree! I used MapSet because it has clean semantics for the problem domain, I expect with small datasets there won't be any performance difference. But looking at my code now I'm not using pop (because `MapSet.pop/2` ecause this doesn't exist, so this may not be helpful to the original discussion about `List.pop/2`

I apologize as I've taken this thread offtopic -- Nathan if it's helpful to you my suggestion/selection implementation is here: https://github.com/bikebrigade/dispatch/blob/main/lib/bike_brigade_web/live/rider_live/index.ex#L21-L90 . Happy to respond to direct emails about it if you have any questions!

Again sorry for veering us offtopic :)

Reply all
Reply to author
Forward
0 new messages