3

让我们看一下文档中的示例:

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

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

Elixir 有多种调度和协议,但在我看来,它的使用有点奇怪。

如果您考虑 OOP 中的多态性或 FP 中的多方法/多分派、协议,那么重点是使代码简短明了,并使程序员无需记住方法的来源。

因此,在 OOP 中,它看起来像下面的代码:

 list.map(square) 

在 FP 多方法中,它看起来像

map(list, square)

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

为什么 Elixir 不使用相同的方法?为什么它需要编写冗长的代码并将决定函数来自何处的责任放在程序员的肩上?

有时不使用 multi 方法并明确指定它是有意义的,例如HttpServer.start(80). 但是对于像each, get,等一般方法来说setsize在没有明确指定它的来源的情况下使用它似乎要容易得多。

附言

似乎使用 Elixir 中的协议实际上可以做到这一点。我想知道-为什么不使用它?我在 GitHub 上看到的 Elixir 项目中的所有代码都使用冗长的符号,例如ModuleName.fnName. 不知道为什么会这样。是否不鼓励使用协议,或者过于复杂而无法在日常任务中使用?

4

4 回答 4

12

您可以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]

也可以写Enum.map,只要map导入Enum模块即可:

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

默认情况下,我们根本不包含该Enum模块。显式导入它会更好,这样任何阅读您的代码的人都会更好地了解所使用的函数来自何处。

换句话说,多个分派和协议仍然没有改变代码始终存在于模块中并且调用始终是合格的这一事实,除非导入。

于 2015-11-07T20:00:55.933 回答
2

在 Elixir(和 Erlang)中,函数总是存在于一个模块中。没有模块就没有功能。甚至你称之为“裸”的函数也在一个模块中——它被调用Kernel(在 Erlang 中它们存在于:erlang模块中)。

Erlang/Elixir 中的函数由模块、名称和数量来标识——只有这三个元素的组合才能告诉你函数的真实身份,但所有这三个元素都只关心函数的命名——而不是它作用的数据.

相反,协议与命名函数无关——它们与处理多态数据有关。所有Enum函数都由Enumerable协议支持——它们可以与列表、范围、映射、集合等一起使用。Enum.map多态函数也是如此,但它被调用Enum.map而不仅仅是map. 如果您对模块名称如此困扰,您可以随时导入要使用“裸”的模块。

于 2015-11-08T09:39:41.530 回答
0

因此,在 OOP 中,它看起来像下面的代码:

list.map(正方形)

在 FP 多方法中,它看起来像

地图(列表,正方形)

在 OOP 中,您获取一个对象(您的列表)并调用该对象正在实现的方法,map在这种情况下

在 Elixir 中,您可以调用存储在 Enum 模块中的 map 函数,其中包含您的集合和要应用的函数。在文档等方面,平面命名空间并不是那么好。通过引用 Enum 下的所有与可枚举相关的函数,您的文档更有意义(但这不是唯一的原因)。

于 2015-11-07T21:41:23.550 回答
0

我对 Elixir很陌生。

结构和协议仅在第一个参数上解决多态性对我来说似乎是有限的。我发现像 Julia、CLOS 和 Clojure 这样的多方法/多分派更强大。

defguard但是,使用带有宏的多参数保护,您似乎可以毫不费力地非常接近多方法。

一个可笑的简单例子看起来像......

defmodule MyModule do
  defguard both_integers(i, j) when is_integer(i) and is_integer(j)

  def add(i, j) when both_integers(i, j) do
    IO.puts i + j
  end

  def add(i, j) do
    IO.puts "do something completely different"
  end
end
于 2019-01-24T01:48:57.827 回答