例如,该Integer.parse/2
函数的 base 的默认值为 10,而String.to_integer/1
两者String.to_integer/2
都存在,其中第二个用于base
需要指定时。
有什么理由以这种方式实施吗?我什么时候应该使用其中一个来定义函数?
我假设的答案是,对于不同的arities,实现存在一些实际差异,而默认值版本共享相同的实现。但是,我不知道为什么在这种情况下会有不同的实现,特别是。
例如,该Integer.parse/2
函数的 base 的默认值为 10,而String.to_integer/1
两者String.to_integer/2
都存在,其中第二个用于base
需要指定时。
有什么理由以这种方式实施吗?我什么时候应该使用其中一个来定义函数?
我假设的答案是,对于不同的arities,实现存在一些实际差异,而默认值版本共享相同的实现。但是,我不知道为什么在这种情况下会有不同的实现,特别是。
在封面下,这几乎是同一件事。当您在 Elixir 中指定默认参数时,会创建两个函数。一种将 arg 设置为默认值的 arity less 和采用附加 arg 的一种。正如您通过自省 Integer 模块所看到的,它导出 parse/1 和 parse/2。
iex(2)> Integer.module_info(:exports)
[__info__: 1, digits: 1, digits: 2, floor_div: 2, "MACRO-is_even": 2,
"MACRO-is_odd": 2, mod: 2, parse: 1, parse: 2, to_char_list: 1, to_charlist: 1,
to_charlist: 2, to_string: 1, to_string: 2, undigits: 1, undigits: 2,
module_info: 0, module_info: 1 ]
在这个例子中String.to_integer
,作者决定更明确地反映实现这一点的底层 Erlang 函数的包装。
接受默认参数的函数被转换为具有相应的多个函数的 arities。
在我看来,这种做法仍然存在,因为使用多个函数头编写的函数来容纳默认参数允许编写比//
-style 默认参数更易理解的保护子句。
此外,由于在 Erlang 中使用多个头定义的函数很普遍(很多 Elixir 代码都是参考它编写的),因此直接翻译保留了不成比例的大量代码,而没有//
.