Более простой способ взять первые N элементов из кортежа?

#elixir

#elixir

Вопрос:

У меня есть функция, которая уменьшает список кортежей из 3 элементов, но когда я закончу, мне нужно вернуть только первые 2 элемента. Соответствие шаблону здесь кажется неуклюжим. Есть ли более элегантный способ взять первые N элементов, что-то вроде Enum.take/2 , но для кортежа?

   def navigate(steps) do
    {x, y, _} = Enum.reduce(steps, {0, 0, 0}, amp;Navigator.do_step/2)
    {x, y}
  end
 

Ответ №1:

Такого метода из коробки не существует, но then/2 для этого можно использовать:

 steps
|> Enum.reduce({0, 0, 0}, amp;Navigator.do_step/2)
|> then(fn {a, b, _} -> {a, b} end)
 

Другим способом (лично мне это не нравится) было бы просмотреть список.

 steps
|> Enum.reduce({0, 0, 0}, amp;Navigator.do_step/2)
|> Tuple.to_list()
|> Enum.take(2)
|> List.to_tuple()
 

Кроме того, в вашем случае вы можете использовать Tuple.delete_at/2

 steps
|> Enum.reduce({0, 0, 0}, amp;Navigator.do_step/2)
|> Tuple.delete_at(2)
 

tuple_take/2 может быть легко реализован как макрос, кстати:

 defmacro tuple_take({:{}, ctx, content}, count) do
  content = Enum.take(content, count)
  {:{}, ctx, content}
end