【问题标题】:Elixir: function overloading with different arityElixir:具有不同数量的函数重载
【发布时间】:2014-06-29 07:30:24
【问题描述】:

有什么方法可以定义具有不同数量的重载函数,例如在 C# 中我可以这样做:

foo(bar)

foo(bar, baz)

在 Elixir 中,这样做的唯一方法是将它们放在单独的模块中,这很快就会变得混乱。有什么办法解决吗?

编辑:我做了一个错误的假设。我看到的重载函数的例子碰巧有相同的数量,所以我(错误地)假设这是一个要求。函数由它们的名称和数量唯一标识,因此您实际上可以重载具有不同数量的函数。

【问题讨论】:

    标签: function overloading clause elixir arity


    【解决方案1】:

    在 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
    

    【讨论】:

    • 第一行,函数的arity怎么可能是1?
    • @tldr:正如 bitwalker 所说, sum/1 和 sum/2 是不同的函数。函数由名称和数量标识。
    • 哦,那是我的一个误解——所有重载函数的例子都有相同的数量,所以我认为这是一个要求。
    • 如果您看到许多具有相同名称和数量的函数,那是因为其中一些函数在其参数上进行了模式匹配,例如上面的示例sum([], acc)sum([h|t], acc)。在这种情况下,函数会按源顺序尝试,因此当您调用 sum([1, 2, 3], 0) 时,它会首先尝试匹配 sum([], acc),这将失败,因为 [1, 2, 3] 不是空列表,然后会尝试 @987654330 @ 这将成功,因为列表有一个头和一个尾。你不能有两个同名和数量的函数在它们的参数上不匹配。
    • 为了澄清我上面的最后一句话,以下是无效的:sum(list, acc), do: acc + 1sum(list, acc), do: acc + 2 但以下是:sum([], acc), do: accsum(list, acc), do: [h|t] = list; sum(t, acc + h) 这样做的原因是因为第一种情况无法区分两个函数子句,这是无效的。第二种情况可以。
    【解决方案2】:

    关于page,请特别参阅第 8.3 节及以下部分。具体如下:

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

    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)
    

    在单个模块中具有多个重载的相同函数名称(尽管该概念在文档中称为clauses)。

    【讨论】:

    • 这只是显示具有相同数量的函数。正如我在问题中提到的,我正在寻找一种方法来重载具有不同数量的函数。
    • 您在问题中的评论“在 Elixir 中,这样做的唯一方法是将它们放在单独的模块中”,这让我认为您不理解多子句函数的概念单模块。另外,我为将来可能会看到此问题的其他人添加了此答案。
    • 我的误解是函数的子句需要具有相同的数量(因为示例中的子句具有相同的数量)。这是不正确的,我已将其添加为我的问题中的编辑。由于您的示例也有具有相同数量的子句,因此与问题无关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多