当我运行以下 Elixir 脚本时,它会打印出{"K", "Y", "L"}.
defmodule MyMod do
def make_tuple(a \\ "X", b \\ "Y", c) do
{a, b, c}
end
end
IO.inspect(MyMod.make_tuple("K", "L"))
Run Code Online (Sandbox Code Playgroud)
为什么不输出{"X", "K", "L"}?这种行为背后的机制是什么?
你是对的:Elixir 使用提供的任何“多余”参数来覆盖函数的部分或全部参数的默认值,从左到右填充。我对此的理解来自 Dave Thomas 的 Programming Elixir 1.6 一书。
诀窍是对于带有默认参数的函数,编译器实际上会生成多个函数。一个函数定义如下:
defmodule Example do
def func(p1, p2 \\ 2, p3 \\ 3, p4) do
IO.inspect [p1, p2, p3, p4]
end
end
Run Code Online (Sandbox Code Playgroud)
实际上被编译成一个看起来像这样的模块:
defmodule Example do
def func(p1, p4) do
func(p1, 2, 3, p4)
end
def func(p1, p2, p4) do
func(p1, p2, 3, p4)
end
def func(p1, p2, p3, p4) do
IO.inspect [p1, p2, p3, p4]
end
end
Run Code Online (Sandbox Code Playgroud)
顺便说一句,您可以通过使用模块的“魔术”module_info/0功能来查看这一点,例如Example.module_info().
使用一些示例值调用您的函数将帮助您了解它们的解释方式,并且可能会有一些惊喜。
Example.func("a", "b") # => ["a",2,3,"b"]
Example.func("a", "b", "c") # => ["a","b",3,"c"] <--- !!!
Example.func("a", "b", "c", "d") # => ["a","b","c","d"]
Run Code Online (Sandbox Code Playgroud)
使用这样的函数可能更容易看到这种行为:
def func(p1 \\ 1, p2 \\ 2) do
IO.inspect [p1, p2]
end
Run Code Online (Sandbox Code Playgroud)
并且只提供 1 个参数来调用它。它将使用左侧提供的参数;仍然使用右侧的默认值:
func("a") # => ["a", 2]
Run Code Online (Sandbox Code Playgroud)
我同意当函数具有不在参数列表末尾的可选参数时,事情会变得混乱。
通过稍微尝试一下,它似乎从左侧分配参数。所以在这种情况下:
defmodule MyMod do
def make_tuple(a \\ "X", b, c \\ "Y", d) do
{a, b, c, d}
end
end
IO.inspect(MyMod.make_tuple(1, 2, 3))
Run Code Online (Sandbox Code Playgroud)
你会得到{1, 2, "Y", 3}——这是对所提供参数的“最左”解释。这会导致一种情况,如果您在“末尾”添加一个参数,它会改变前面的参数的含义,并且(我认为)这就是人们通常避免使用不在参数列表末尾的可选参数的原因。
| 归档时间: |
|
| 查看次数: |
98 次 |
| 最近记录: |