为啥在 elixir 中定义命名函数有两种方式?

Posted

技术标签:

【中文标题】为啥在 elixir 中定义命名函数有两种方式?【英文标题】:Why are there two ways to define named functions in elixir?为什么在 elixir 中定义命名函数有两种方式? 【发布时间】:2016-01-28 12:06:39 【问题描述】:

在 elixir 中,可以用两种不同的方式定义“sum”函数:

def sum, do: 0
def sum(a), do: a
def sum(a, b), do: a + b
def sum(a, b, c), do: a + b + c

def sum() do 0 end
def sum(a) do a end
def sum(a,b) do a + b end
def sum(a,b,c) do a + b+ c end

我什至可以混合使用这两种方法:

def sum() do 0 end
def sum(a) do a end
def sum(a,b) do a + b end
def sum(a,b,c), do: a + b + c

我的问题是:为什么有两种方法可以达到相同的效果?在内联函数的情况下,第二个是首选吗?它们各自的优点是什么?

提前致谢!

【问题讨论】:

【参考方案1】:

do...end 格式是do: 格式的语法糖。

这不仅适用于函数,也适用于ifcasecond等。

case 1, do: (1 -> "a")

case 1 do
  1 -> "a"
end

一般来说,do...end 格式是首选,除非函数定义短到可以放在一行中。

do 在这种情况下实际上是关键字列表中的一个参数。 if 宏的实现类似于:

do_clause = Keyword.get(clauses, :do, nil)
else_clause = Keyword.get(clauses, :else, nil)

这将获取do...else...end 块内的表达式:

if foo do
  #this gets stored in do_clause
else
  #this gets stored in else_clause
end

注意if的实现略有变化,你可以在https://github.com/elixir-lang/elixir/blob/1a7412502fd581da8ef1378fcd5a057ab96378f7/lib/elixir/lib/kernel.ex#L2294看到我指的版本

【讨论】:

【参考方案2】:

这是为了程序员的方便。以任何上述方式定义函数不会对实际函数产生任何影响。

do..enddo: 的语法糖。这意味着它是一种使事情更容易阅读或表达的语法。它使人类使用的语言“更甜”:可以更清晰、更简洁地表达事物,或者以某些人可能更喜欢的另一种风格表达。[wikipiedia]

一般而言,do: 语法适用于单行,do..end 适用于多行

def count(limit), do: count(1,limit)

defp count(current,limit) when current <= limit do
    IO.inspect(current)
    count(current+1,limit)
end

#The underscore means we dont care what the arguments are
defp count(_,_), do: IO.puts("finished")

【讨论】:

以上是关于为啥在 elixir 中定义命名函数有两种方式?的主要内容,如果未能解决你的问题,请参考以下文章

回调函数

Elixir:应用程序立即退出,或者在运行 distillery 包时没有收到输入。为啥它会以这种方式工作,以及如何解决它?

为啥sql server身份验证失败

在 Elixir 中传递和使用命名函数?

js twe

Elixir/Erlang 中的命名函数是不是有等效于 __MODULE__ 的方法?