2015-12-10 18 views

cevap

63

bir boru hattı işlevleri kullanırken, bir monad kütüphane veya iç içe durum ifadeleri kullanması gerekir ya (özel işlevleri kullanarak refactored, ancak yine de uzun olmakla sona ereceğini) . with/1, bu sorunu çözmek için farklı bir yol sağlar. Aynı kod with kullanılarak

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 

Ve:

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

İşte

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 

işlevlerini kullanmak için refactored aynı şeydir: Burada

original proposal bir örnektir Bu, with yalnızca tutulacağı için çalışır Değer, soldaki desene uyuyorsa zincirleme. Değilse, zincir iptal edilir ve eşleşen olmayan ilk sonuç döndürülür. herhangi deseni ile kullanılabilir ile değil, sadece {:ok, foo} ve {:error, reason} (her ne nedenle with/1 çağrı Bu fazlalaştı {:error, :enoent}.

dönecektir bu {:ok, binary} eşleşmiyor - Örneğin dosya daha sonra File.read(path){:error, :enoent} dönecektir yoksa çok yaygın bir kullanım durumudur).

+2

Gerçekten de "sürümüyle" çok daha iyi görünüyor. Bu çok kullanışlı. – diogovk

+0

Ben bence 'defp read_chunks' sadece okunmalıdır '': beam_lib.chunks (binary,: abstract_code) '(yani, ilk' {: ok, 'olmadan) – Grandpa

+0

Ben ok_jose gibi hissediyorum (https: // github. com/vic/ok_jose) çok daha temiz görünüyor (adın dışında). Bunun yerine kullanmamak için herhangi bir sebep var mı? – Johannes

15

doktor diyor Ayrıca, "çıplak ifadeleri" zincir edebilirsiniz:

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

değişken header sadece with deyimi içinde satışa sunulacak. Daha fazla bilgi için https://gist.github.com/josevalim/8130b19eb62706e1ab37

2

with ifadesinden when muhafazasını kullanabilirsiniz. E.g,

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 , %{}}) 
İlgili konular