iex> handle_result = fn
...> {:ok, result} -> IO.puts "Handling result..."
...> {:ok, _} -> IO.puts "This would be never run as previous will be matched beforehand."
...> {:error} -> IO.puts "An error has occurred!"
...> end
iex> some_result = 1
iex> handle_result.({:ok, some_result})
Handling result...
iex> handle_result.({:error})
An error has occurred!
# 传入一个不包含相应键值的字典后,会产生如下错误
...> Greeter1.hello(%{age: "95", favorite_color: "Taupe"})
** (FunctionClauseError) no function clause matching in Greeter3.hello/1
The following arguments were given to Greeter3.hello/1:
# 1
%{age: "95", favorite_color: "Taupe"}
iex:12: Greeter3.hello/1
当它在传入的字典中找到相应的键 :name 时,这个匹配就成立了。匹配成功的结果就是,右边字典中 :name 键对应的值(在 fred 字典中),就赋予到左边的变量(person_name)上。
那么,如果我们除了希望把 Fred 的姓名赋值到 person_name 外,我们还希望保留整个人物信息的字典,要怎么做呢?比如说我们希望在和他打招呼后运行 IO.inspect(fred)。上面的做法,因为我们只是模式匹配了 :name 这个键值,也因此只是把它的值赋予了一个变量,函数本身并不知道 Fred 其它的信息。
为了保存所有的数据,我们需要把整个字典,赋予一个它专属的变量。
我们来定义一个新的函数:
defmodule Greeter2 do
def hello(%{name: person_name} = person) do
IO.puts "Hello, " <> person_name
IO.inspect person
end
end
defmodule Greeter do
def hello(name), do: phrase <> name
defp phrase, do: "Hello, "
end
iex> Greeter.hello("Sean")
"Hello, Sean"
iex> Greeter.phrase
** (UndefinedFunctionError) function Greeter.phrase/0 is undefined or private
Greeter.phrase()
defmodule Greeter do
def hello(names) when is_list(names) do
names
|> Enum.join(", ")
|> hello
end
def hello(name) when is_binary(name) do
phrase() <> name
end
defp phrase, do: "Hello, "
end
iex> Greeter.hello ["Sean", "Steve"]
"Hello, Sean, Steve"
默认参数
如果想给参数设置默认值,我们可以用 argument \\ value 语法:
defmodule Greeter do
def hello(name, language_code \\ "en") do
phrase(language_code) <> name
end
defp phrase("en"), do: "Hello, "
defp phrase("es"), do: "Hola, "
end
iex> Greeter.hello("Sean", "en")
"Hello, Sean"
iex> Greeter.hello("Sean")
"Hello, Sean"
iex> Greeter.hello("Sean", "es")
"Hola, Sean"
当我们同时使用卫兵和默认参数值的时候,会遇到问题,先看一下程序会报什么错:
defmodule Greeter do
def hello(names, language_code \\ "en") when is_list(names) do
names
|> Enum.join(", ")
|> hello(language_code)
end
def hello(name, language_code \\ "en") when is_binary(name) do
phrase(language_code) <> name
end
defp phrase("en"), do: "Hello, "
defp phrase("es"), do: "Hola, "
end
** (CompileError) iex:31: definitions with multiple clauses and default values require a header. Instead of:
def foo(:first_clause, b \\ :default) do ... end
def foo(:second_clause, b) do ... end
one should write:
def foo(a, b \\ :default)
def foo(:first_clause, b) do ... end
def foo(:second_clause, b) do ... end
def hello/2 has multiple clauses and defines defaults in one or more clauses
iex:31: (module)