2017-09-09 3 views
2

Dans le livre « Programmation Elixir » Dave Thomas montre un exempleComment fonctionnent les fonctions dans Elixir?

handle_open = fn 
    {:ok, file} -> "Read data: #{IO.read(file, :line)}" 
    {_, error} -> "Error: #{:file.format_error(error)}" 
end 

handle_open.(File.open("code/intro/hello.exs")) 
handle_open.(File.open("nonexistent")) 

Je ne comprends pas pourquoi deuxième appel de la fonction passe en second flux. aussi pourquoi nous ne transmettons pas un argument en func:

handle_open = fn(file) 

?

Répondre

3

Il s'agit d'une fonction anonyme à plusieurs clauses. handle_open a 2 clauses, une pour faire correspondre les arguments avec le modèle {:ok, file} et l'autre avec {_, error}. Le premier modèle qui correspond aux arguments est exécuté. Le code donné est presque [1] équivalent à ce qui suit:

handle_open = fn arg -> 
    case arg do 
    {:ok, file} -> ... 
    {_, error} -> ... 
    end 
end 

Donc, si le fichier existe, File.open retournera {:ok, file} et la première clause sera exécutée. Si ce n'est pas le cas, {:error, error} sera retourné, ce qui correspondra à la seconde clause et l'exécutera.

[1]: "Presque" car l'erreur déclenchée lorsqu'aucun des motifs ne correspondra sera légèrement différente pour les deux cas.

+0

Merci! Je suis un peu pressé avec ça ... –

0

Cela ne fait que simuler le comportement de correspondance de motif d'Elixir.

Comme vous pouvez également faire correspondre des motifs à vos fonctions de module.

defmodule MyModule do 
    def read_file(path) do 
    File.open(path) |> handle_file() 
    end 

    defp handle_file({:ok, file}) do 
    // File there.. 
    end 

    defp handle_file({_, error}) do 
    // Could not open file.. because of `error` 
    end 
end 

Comme dans l'exemple du livre, je voudrais essayer d'ouvrir le fichier dans une clause de cas et déléguer le résultat à la fonction appropriée:

defmodule FileReader do 

    def read_file(path) do 
    case File.open(path) do 
     {:ok, file} -> handle_file(file) 
     {_, error} -> handle_error(error) 
    end 
    end 

    defp handle_file(file) do 
    // File there.. 
    end 

    defp handle_error(error) do 
    // 
    end 
end