vida tutorial también sinonimo programación lenguaje inmortal framework buscó elixir

tutorial - ¿Cómo usar la palabra clave “con” en Elixir y para qué sirve?



elixir también se buscó (3)

En el elixir 1.2 han incluido la palabra clave "con", pero no me queda claro para qué sirve.

¿Cómo y en qué situación lo usaría?


En las versiones de Elixir anteriores a 1.2 cuando se usan funciones en una tubería, tendría que usar una biblioteca de mónadas o declaraciones de casos de anidamiento (que podrían ser refactorizadas usando funciones privadas, pero aún así serían verbales). with/1 permite una forma diferente de resolver este problema.

Aquí hay un ejemplo de la propuesta original :

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

Aquí está lo mismo refactorizado para usar funciones:

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

Y el mismo código usando with :

with {:ok, binary} <- File.read(path), {:ok, data} <- :beam_lib.chunks(binary, :abstract_code), do: {:ok, wrap(data)}

Esto funciona porque with solo mantendrá el encadenamiento si el valor coincide con el patrón de la izquierda. Si no, la cadena se cancela y se devuelve el primer resultado no coincidente. Por ejemplo, si el archivo no existe, File.read(path) devolverá {:error, :enoent} - esto no coincide {:ok, binary} por lo que la llamada with/1 devolverá {:error, :enoent}.

Vale la pena señalar que with puede usarse con cualquier patrón, no solo {:ok, foo} y {:error, reason} (aunque es un caso de uso muy común).


También puede encadenar "expresiones simples", como dice el documento:

with {:ok, binary} <- File.read(path), header = parse_header(binary), {:ok, data} <- :beam_lib.chunks(header, :abstract_code), do: {:ok, wrap(data)}

El header variable estará disponible solo dentro de la sentencia with . Más información en https://gist.github.com/josevalim/8130b19eb62706e1ab37


Una cosa para mencionar, se puede usar when guardas with declaración. P.ej,

defmodule Test do def test(res) do with {:ok, decode_res} when is_map(decode_res) <- res do IO.inspect "ok" else decode_res when is_map(decode_res) -> IO.inspect decode_res _ -> IO.inspect "error" end end end Test.test({:ok , nil}) Test.test({:ok , 12}) Test.test({:ok , %{}})