#elixir
#elixir
Вопрос:
Я все еще новичок в Elixir. Я пытаюсь создать метод, который принимает список запросов и обрабатывает каждый запрос. Верните {:ok, «success»}, если все прошло или {:error, error_reason}, если один не удался.
На других языках я могу сделать что-то подобное. Предположим, что функция процесса возвращает либо {:ok, «success»}, либо {:error, error_reason} .
def func(requests):
for request in requests:
if {:error, error_reason} <- process(request):
return {:error, error_reason}
return {:ok, "success"}
end
Каков правильный способ сделать это в мире Elixir?
Ответ №1:
Я бы использовал рекурсию:
def func([head | tail]) do
case process(head) do
{:error, reason} -> {:error, reason}
{:ok, _} -> func(tail)
end
end
def func([]), do: {:ok, "success"}
Циклы по своей сути обязательны, а Elixir по сути является функциональным языком, поэтому рекурсия и функции более высокого порядка являются более естественной альтернативой использованию циклов, я думаю.
Комментарии:
1. Ах, извините, я как-то замалчивал эту часть. Тогда
Enum.find
это определенно не подходит. Я бы всегда выбирал функцию более высокого порядка, если она доступна, но, поскольку я не думаю, что есть одна легкодоступная, которая применима к этому сценарию, я бы реализовал ее, используя вместо этого рекурсию. Я отредактировал свой ответ, слегка изменив предыдущее рекурсивное предложение, которое, я надеюсь, лучше соответствует тому, о чем вы просите.2.
Enum.find/2
на самом деле работает. Я немного поиграл с этой функцией, какfuns = (1..100) |> Enum.map(amp;(fn-> IO.inspect(amp;1) end))
и тогдаEnum.find(funs, amp;(amp;1.() == 5))
, она печатает только 5 чисел, а не 100 чисел.3. Интересно, @Aetherus, я действительно могу воспроизвести и ваш результат, но это, похоже, противоречит документации: «Наконец, обратите внимание, что функции в модуле Enum готовы: они будут проходить через перечислимое, как только они будут вызваны. Это особенно опасно при работе с бесконечными перечисляемыми. В таких случаях вам следует использовать модуль Stream, который позволяет лениво выражать вычисления, не проходя коллекции, и работать с, возможно, бесконечными коллекциями. » Поэтому я не уверен, насколько безопасно было бы полагаться на это.
4. В
Stream
документации также уточняется, что это определяющее различие. И, к сожалению, также нетStream.find
или эквивалентных функций.5. В
Stream
данном случае лень функций не имеет значения.Stream
функции выполняются таким образом, что по запросу «нисходящего потока» он извлекает только один элемент из «восходящего потока», обрабатывает его и передает его нисходящему потоку.Stream
функции могут выполнять только локальные операции (для которых требуется только текущий элемент). С другой стороны,Enum
функции просто используют столько элементов, сколько необходимо для достижения вывода, и возвращают весь вывод, поэтомуEnum
функции могут выполнять нелокальные операции, такие какreduce
andgroup_by
иfind
.