As you might see, List.pop_at/3
is itself implemented using recursion, :lists.reverse
, and head access. That said, there is no way to directly access the last element in the list.
On the other hand, if you are concern, that there can’t be more than, say, N
elements in the list, the direct pattern match is still achievable:
defmodule MatchInTheMiddle do
@n 10
Enum.each(0..@n, fn i ->
@match_clause Enum.map(0..i, fn j -> {:"p#{j}", [], Elixir} end)
def match_middle(unquote(
[{:_head, [], Elixir}] ++ @match_clause ++ [{:_last, [], Elixir}])
), do: IO.inspect unquote(@match_clause)
end)
end
And, yes, the graceful fallback for short and long lists:
def match_middle([]), do: []
def match_middle([_]), do: []
def match_middle([_head | tail]) do
with [_tail | middle] <- :lists.reverse(tail), do: middle
end
MatchInTheMiddle.match_middle([1,2,3,4])
#⇒ [2,3]
This is not as elegant as you probably expected it to be, but in some cases it might be helpful, since these clauses are compiled into pattern matches and on huge amounts of data this is rather more efficient that Enum
operations.