为什么Elixir不使用Multimethods/Protocols?

Ale*_*hin 3 functional-programming protocols elixir multimethod

让我们看一下docs中的示例:

square = fn(x) -> x * x end
list = [1, 2, 3, 4]
Enum.map(list, square)
Run Code Online (Sandbox Code Playgroud)

为什么要明确写Enum.map?为什么它不使用干净和短的符号map [1, 2, 3, 4], square

Elixir有多个Dispatch和Protocols,但对我来说它似乎有点奇怪.

如果你考虑OOP中的多态性或MultiModods/Multiple Dispatch,FP中的协议,重点是使代码简短,简洁,让程序员内存不再记住方法的来源.

所以,在OOP中它看起来像下面的代码:

 list.map(square) 
Run Code Online (Sandbox Code Playgroud)

在FP多方法中它看起来像

map(list, square)
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,编译器/解释器都使用参数类型来确定map应该使用哪种方法.

为什么Elixir不使用相同的方法?为什么需要编写详细的代码并负责决定函数的来源在程序员的肩膀上?

有时,不使用多方法并明确指定它是有意义的HttpServer.start(80).但是,对于像一般方法each,get,set,size等它看起来像它更容易使用它没有明确指定它从何而来.

PS

似乎实际上可以使用Elixir中的Protocols来实现.我想知道 - 为什么不使用它?我在GitHub上看到的Elixir项目中的所有代码都使用了冗长的详细符号ModuleName.fnName.不知道为什么会这样.协议的使用是否不鼓励,或者太复杂,无法在日常任务中使用?

Jos*_*lim 11

您可以Enum.map以可扩展的方式使用不同的参数,因为它是使用协议实现的:

iex> Enum.map [1, 2, 3], fn x -> x * x end
[1, 4, 9]

iex> Enum.map 1..3, fn x -> x * x end
[1, 4, 9]
Run Code Online (Sandbox Code Playgroud)

你也可以写Enum.mapmap,只要你导入Enum模块:

iex> import Enum
iex> map [1, 2, 3], fn x -> x * x end
[1, 4, 9]
Run Code Online (Sandbox Code Playgroud)

我们Enum默认不包含该模块.显式导入它要好得多,这样任何阅读代码的人都可以更好地了解所使用的函数来自何处.

换句话说,多个调度和协议仍然不会改变代码始终存在于模块内的事实,并且除非导入,否则调用始终是合格的.

  • Elixir中的协议提供开放的ad-hoc多态性.上面的响应显示了它在第一个参数上的多态性.甚至Elixir中的常规函数​​子句提供了一种称为闭合ad-hoc多态的多态性形式.多方法是多态的另一种形式,Elixir不支持.泛型也是另一种形式的多态,称为参数多态,甚至继承称为子类型多态.多态性是一个非常广泛的术语,所以要小心不要让它混淆. (2认同)