有什么问题:is_number if true do 1 end
What's wrong with: is_number if true do 1 end
为什么第二种形式被解析为传递给 is_number 的 2 个参数?
is_number if true, do: 1
true
is_number if true do 1 end
** (CompileError) iex:42: undefined function is_number/2
我们可以使用 quoting mechanism 查看表达式在 Elixir 中的解析方式。
iex(6)> IO.puts Macro.to_string(quote do: (is_number if true, do: 1))
is_number(if(true) do
1
end)
:ok
iex(7)> IO.puts Macro.to_string(quote do: (is_number if true do 1 end))
is_number(if(true)) do
1
end
:ok
所以在你的第一种情况下,do
被解析为 if
的参数,整个事情被传递给 is_number
。在第二个中,do
具有不同的优先级,最终绑定到 is_number
调用自身作为第二个参数,因此我们最终调用 if/1
和 is_number/2
,这是废话。
至于为什么会这样,通常使用 do
来捕获完整的表达式作为语句,例如
if something_really_complicated arg1, arg2, arg3 do
# ...
end
因此,在这种情况下,尽可能松散地绑定 do
是有意义的。相反,如果我们尝试将 do:
作为带有显式逗号的关键字参数传递,那么它就像任何其他参数一样只是一个参数,因此它遵循通常的参数传递规则而不是特殊规则。
在像 Elixir 这样的语言中要记住的关键是,许多在其他语言中是关键字的东西在 Elixir 中实际上并不存在。 if
语句的解析方式与宏完全相同,您可以轻松编写自己的 if
宏,而 do:
实际上只是一个关键字参数,附加了一些语法糖,而不是特定于任何特定控制语句的任何内容。这是使 Elixir(和公司)非常适合 domain-specific 任务的重要原因。
为什么第二种形式被解析为传递给 is_number 的 2 个参数?
is_number if true, do: 1
true
is_number if true do 1 end
** (CompileError) iex:42: undefined function is_number/2
我们可以使用 quoting mechanism 查看表达式在 Elixir 中的解析方式。
iex(6)> IO.puts Macro.to_string(quote do: (is_number if true, do: 1))
is_number(if(true) do
1
end)
:ok
iex(7)> IO.puts Macro.to_string(quote do: (is_number if true do 1 end))
is_number(if(true)) do
1
end
:ok
所以在你的第一种情况下,do
被解析为 if
的参数,整个事情被传递给 is_number
。在第二个中,do
具有不同的优先级,最终绑定到 is_number
调用自身作为第二个参数,因此我们最终调用 if/1
和 is_number/2
,这是废话。
至于为什么会这样,通常使用 do
来捕获完整的表达式作为语句,例如
if something_really_complicated arg1, arg2, arg3 do
# ...
end
因此,在这种情况下,尽可能松散地绑定 do
是有意义的。相反,如果我们尝试将 do:
作为带有显式逗号的关键字参数传递,那么它就像任何其他参数一样只是一个参数,因此它遵循通常的参数传递规则而不是特殊规则。
在像 Elixir 这样的语言中要记住的关键是,许多在其他语言中是关键字的东西在 Elixir 中实际上并不存在。 if
语句的解析方式与宏完全相同,您可以轻松编写自己的 if
宏,而 do:
实际上只是一个关键字参数,附加了一些语法糖,而不是特定于任何特定控制语句的任何内容。这是使 Elixir(和公司)非常适合 domain-specific 任务的重要原因。