Function Elixir:具有不同算术性的函数重载

Function Elixir:具有不同算术性的函数重载,function,overloading,clause,elixir,arity,Function,Overloading,Clause,Elixir,Arity,有没有办法用不同的算术定义重载函数,例如在C#中,我可以这样做: foo(bar) 或 在Elixir中,实现这一点的唯一方法是将它们放在单独的模块中,这将很快变得混乱。有什么办法吗 编辑:我做了一个错误的假设。我看到的重载函数的示例恰好具有相同的算术性,因此我(错误地)认为这是一个要求。函数是通过名称和算术唯一标识的,因此实际上可以用不同的算术重载函数。在Erlang和Elixir中,与许多其他语言(如C#)不同,函数是通过名称和算术唯一标识的,因此从技术上讲foo(bar)和foo(bar

有没有办法用不同的算术定义重载函数,例如在C#中,我可以这样做:

foo(bar)

在Elixir中,实现这一点的唯一方法是将它们放在单独的模块中,这将很快变得混乱。有什么办法吗


编辑:我做了一个错误的假设。我看到的重载函数的示例恰好具有相同的算术性,因此我(错误地)认为这是一个要求。函数是通过名称和算术唯一标识的,因此实际上可以用不同的算术重载函数。

在Erlang和Elixir中,与许多其他语言(如C#)不同,函数是通过名称和算术唯一标识的,因此从技术上讲
foo(bar)
foo(bar,baz)
是完全不同的功能。但这实际上只是一个技术问题,要在Elixir中编写一个“重载”函数,您需要编写类似于以下定义的
sum

defmodule Math do
  def sum(list),       do: sum(list, 0)
  def sum([], acc),    do: acc
  def sum([h|t], acc), do: sum(t, acc + h)
end
关于这一点,请特别参见第8.3节和下文。具体而言:

函数声明还支持保护和多个子句。如果函数有多个子句,Elixir将尝试每个子句,直到找到一个匹配的子句。下面是一个函数的实现,用于检查给定的数字是否为零:


在单个模块中具有多个重载的相同函数名(尽管在文档中称为
子句

在第一行中,函数的arity怎么可能是1?@tldr:正如bitwalker所说,sum/1和sum/2是不同的函数。函数是通过名称和算术来识别的。哦,这对我来说是一个误解-所有重载函数的示例都具有相同的算术,所以我假设这是一个要求。如果你看到许多函数具有相同的名称和算术,那是因为其中一些函数的参数是模式匹配的,与上面示例中的
sum([],acc)
sum([h | t],acc)
类似。在这种情况下,函数是按源代码顺序尝试的,因此当您调用
sum([1,2,3],0)
时,它将首先尝试与
sum([],acc)
进行匹配,这将失败,因为
[1,2,3]
不是空列表,然后将尝试
sum([h | t],acc)
,这将成功,因为列表有头和尾。您不能有两个名称和算术相同的函数在其参数上不匹配。为了澄清我上面的陈述,以下内容无效:
sum(list,acc),do:acc+1
sum(list,acc),do:acc+2
,但以下内容是:
sum([],acc),do:acc
sum(list,acc),do:[h | t]=list;sum(t,acc+h)
原因是第一种情况无法区分两个函数子句,这是无效的。但是,第二种情况可以。这只是显示具有相同算术数的函数。正如我在问题中提到的,我正在寻找一种方法来重载具有不同算术的函数。你在问题中的评论“在Elixir中,唯一的方法是将它们放在单独的模块中”,这让我觉得你不理解在单个模块中使用多子句函数的想法。另外,我为将来可能看到这个问题的其他人添加了这个答案。我的误解是函数的子句需要具有相同的算术(因为示例中有具有相同算术的子句)。这是不正确的,我在问题中添加了它作为编辑。由于您的示例中也有具有相同算术的子句,因此它与问题无关。
defmodule Math do
  def sum(list),       do: sum(list, 0)
  def sum([], acc),    do: acc
  def sum([h|t], acc), do: sum(t, acc + h)
end
defmodule Math do
  def zero?(0) do
    true
  end

  def zero?(x) when is_number(x) do
    false
  end
end

Math.zero?(0)  #=> true
Math.zero?(1)  #=> false

Math.zero?([1,2,3])
#=> ** (FunctionClauseError)