В elixir 1.2 они включили ключевое слово "с", но мне не совсем понятно, для чего он предназначен.
Как и в какой ситуации я буду использовать его?
В elixir 1.2 они включили ключевое слово "с", но мне не совсем понятно, для чего он предназначен.
Как и в какой ситуации я буду использовать его?
В версиях Elixir до 1.2 при использовании функций в конвейере вам нужно будет либо использовать библиотеку monad или инструкции для случая гнезда (которые могут быть реорганизованы с использованием частных функций, но все равно в конечном итоге будут подробными). with/1 позволяет по-другому решить эту проблему.
Вот пример из оригинального предложения:
case File.read(path) do
{:ok, binary} ->
case :beam_lib.chunks(binary, :abstract_code) do
{:ok, data} ->
{:ok, wrap(data)}
error ->
error
end
error ->
error
end
Вот то же самое, что реорганизовано для использования функций:
path
|> File.read()
|> read_chunks()
|> wrap()
defp read_chunks({:ok, binary}) do
{:ok, :beam_lib.chunks(binary, :abstract_code)}
end
defp read_chunks(error), do: error
defp wrap({:ok, data}) do
{:ok, wrap(data)}
end
defp wrap(error), do: error
И тот же код с помощью with
:
with {:ok, binary} <- File.read(path),
{:ok, data} <- :beam_lib.chunks(binary, :abstract_code),
do: {:ok, wrap(data)}
Это работает, потому что with
будет сохранять цепочку только в том случае, если значение соответствует шаблону слева. Если нет, цепочка прерывается и возвращается первый результат несогласования. Например, если файл не существует, то File.read(path)
вернет {:error, :enoent}
- это не соответствует {:ok, binary}
, поэтому вызов with/1
вернет {:error, :enoent}.
Стоит отметить, что с может использоваться с любым шаблоном, а не только {:ok, foo}
и {:error, reason}
(хотя это очень распространенный вариант использования).
Вы также можете связать "голые выражения", как сообщает doc:
with {:ok, binary} <- File.read(path),
header = parse_header(binary),
{:ok, data} <- :beam_lib.chunks(header, :abstract_code),
do: {:ok, wrap(data)}
Переменная header
будет доступна только внутри оператора with
. Дополнительная информация на https://gist.github.com/josevalim/8130b19eb62706e1ab37