有人可以解释一下为什么这不起作用吗?
当您调用函数时,elixir 从定义中的第一个函数子句开始,并尝试将函数调用中指定的参数与函数定义中的参数相匹配。如果没有匹配,elixir 然后尝试下一个函数子句。当找到匹配项时,执行相应的函数体。如果没有任何函数子句匹配,那么您会收到 function_clause 错误。
让我们通过一个例子。如果你写:
def go({1, 2}, :cat) do
IO.puts "I must have matched the function call."
end
那么您可以像这样调用该函数:
iex(2)> A.go({1, 2}, :cat)
I must have matched the function call.
:ok
但是,如果你尝试:
ex(3)> A.go("hello", 10)
** (FunctionClauseError) no function clause matching in A.go/2
The following arguments were given to A.go/2:
# 1
"hello"
# 2
10
a.ex:2: A.go/2
您会收到函数子句错误,因为定义的函数子句没有go()
匹配函数调用:
function call: A.go("hello", 10)
| |
{1,2} = "hello | | :cat = 10
V V
function def: def go({1, 2}, :cat) do
函数调用中唯一go()
能匹配{1, 2}
函数定义中元组{1, 2}
的参数是元组,函数调用中唯一能匹配:cat
函数定义中原子的参数是原子:cat
。
但是,函数定义中的变量匹配任何东西。合法变量名称的一些示例是:x
、y
和。所以,如果你这样定义:_x
_
go()
def go(_x, _y) do
IO.puts "I must have matched the function call."
end
那么两个函数调用将匹配:
iex(3)> c "a.ex"
warning: redefining module A (current version defined in memory)
a.ex:1
[A]
iex(4)> A.go("hello", 10)
I must have matched the function call.
:ok
iex(5)> A.go({1, 2}, :cat)
I must have matched the function call.
:ok
如果在 go() 定义中添加第二个函数子句:
def go(_x, _y) do
IO.puts "I must have matched the function call."
end
def go(_, _) do
IO.puts "I will never match"
end
第一个函数子句仍将匹配任何两个参数,并且因为是这种情况,所以第二个函数子句将永远不会执行——所以编译器会给你一个警告,相当于:
什么?当第二个函数子句永远不会匹配因此永远不会执行时,您为什么要在第二个函数子句中乱写所有垃圾?!控制!
当您在函数定义中进行模式匹配时,事情会变得有些棘手,例如:
def go(%{a: val}=map, x) do
请参阅此处了解其工作原理。