什么是 Elixir Bang 函数?

What are Elixir Bang Functions?

我在阅读 Phoenix 教程(在 Incoming Events 部分)时首先注意到一个尾随 exclamation-mark/bang(!) 的函数

def handle_in("new_msg", %{"body" => body}, socket) do
    broadcast! socket, "new_msg", %{body: body}
    {:noreply, socket}
end

结尾的感叹号是什么意思?它有什么作用吗? 我一直在四处搜索并尝试查找,但我不确定我使用的是正确的术语。到目前为止,该函数似乎仅作为约定会在失败时引发错误,但它总是意味着。

我看到的唯一提到它出现在 Dave Thomas 的 "Programming Elixir" 中:

Identifiers in Elixir are combinations of upper and lower case ASCII 
characters, digits, and underscores. Function names may end with a 
question mark or an exclamation point.

而且在 the documentation 中提到:

Notice that when the file does not exist, the version with ! raises an
error. The version without ! is preferred when you want to handle
different outcomes using pattern matching...

这些都没有解释这是否是其他长生不老药或炼金术士或其他任何人使用的惯例。请帮忙。

这个:

Notice that when the file does not exist, the version with ! raises an error. The version without ! is preferred when you want to handle different outcomes using pattern matching...

看源码就更清楚了。函数名中的 ! 符号只是一种语法约定。如果您看到一个名称中包含 ! 符号的函数,这意味着可能存在一个具有相同名称但没有 ! 符号的函数。这两个函数会做同样的事情,但它们会以不同的方式处理错误。

没有!的函数只会return给你一个错误。您将需要知道一种错误类型并根据您的类型处理它。查看 broadcast/3 函数(variant 没有 !):

  def broadcast(server, topic, message) when is_atom(server),
    do: call(server, :broadcast, [:none, topic, message])

它只是调用给定的服务器并return它的结果。 broadcast!/3 函数会做同样的事情,但是:它会在没有 ! 的情况下调用 broadcast 函数,将检查它的结果并引发 BroadcastError exception:

  def broadcast!(server, topic, message) do
    case broadcast(server, topic, message) do
      :ok -> :ok
      {:error, reason} -> raise BroadcastError, message: reason
    end
  end

马克,你基本上是对的 - 如果出现问题,一定要提出错误。

关于此 page 的某种文档讨论了文件访问 (向下滚动到 trailing bang 短语)

这只是一种命名约定。检查这个答案 -

! - 如果函数遇到错误,将引发异常。

一个很好的例子是Enum.fetch!(它也有一个相同的Enum.fetch,它不会引发异常)。在给定的索引(从零开始)找到元素。如果给定位置超出集合范围,则引发 OutOfBoundsError。