2015-10-24 92 views
18

我第一次注意到了尾隨感嘆號標記/感嘆號(!)經歷鳳凰教程(在Incoming Events部分),而什麼是Elixir Bang功能?

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

是什麼後感歎號的意思是一個函數?它有什麼作用嗎?我一直在四處搜尋,並試圖尋找,但我不知道我使用正確的條款。到目前爲止,僅僅作爲約定的函數似乎會在錯誤失敗時引發錯誤,但它總是意味着錯誤。

唯一提到我看到它出現在「編程花好月圓」由戴夫·托馬斯:

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... 

這些都不解釋了,如果這是一個約定其他藥劑師或煉金術士或任何使用。請幫忙。

回答

10

此:

注意,當文件不存在,該版本!引發了 錯誤。版本沒有!當你想處理 使用模式匹配的不同結果是首選...

將更清晰,如果你會看看源代碼。函數名中的!符號只是一個語法協議。如果您看到一個名稱中包含!符號的函數,則表示可能存在具有相同名稱的函數,但不包含!符號。這兩個函數都會做同樣的事情,但它們會以不同的方式處理錯誤。

沒有!的函數只會向您返回錯誤。您需要知道一種錯誤類型,並根據您的類型進行處理。看在broadcast/3功能(variant!):

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

它只是使調用給定服務器並返回其結果。該broadcast!/3功能也將這樣做,但:它會調用broadcast功能,無需!,將檢查其結果,提高BroadcastErrorexception

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

感謝您花時間從鳳凰來源提供一個很好的例子。它完美地回答了我的問題。我被困在你的答案和我選擇的答案之間,因爲兩者都很好地解釋了我的問題。我選擇不選這個,因爲它專注於鳳凰使用'!',不幸的是,在我的問題中沒有表達出來,我對Elixir的慣例比Phoenix更感興趣。 – Marc

+1

我要吃我自己的單詞 - 並接受你的答案,因爲它指出了@MoxleyStratton提到的一個重要細節 - 「爆炸慣例適用於有兩個版本的函數 - 一個引發異常(爆炸版本),而不是。「 – Marc

2

基本上,你這樣做是正確馬克 - 這是一個約定,說確實引起如果事情出錯,會出現錯誤。

有文檔,一類,在此page談到有關文件訪問 (向下滾動到短語後爆炸

+0

我的主要問題是,文檔是順利完成的,我們作爲Elixir社區預計會抓住細節。我很高興我能夠收集到一些東西,並且提供了它的公認使用的「社區文檔」:) TY – Marc

+0

我覺得這個答案很容易讓人誤解。讀一下它,開發人員可以得出結論,當創建一個引發錯誤的函數時,它應該用一個bang(!)來命名。這不是爆炸公約的意圖。 @ 0xAX說得對,看到一個爆炸函數「這意味着可能有一個名稱相同的函數,但沒有!符號」。爆炸慣例適用於有兩個版本的函數 - 一個引發異常(爆炸版本),另一個不引發異常。 –

+0

@MoxleyStratton回顧這個問題(並接受答案)我同意你的觀點(並且不同意我以前的決定)。 – Marc

11

它只是一個命名約定。檢查這個答案 - What's the meaning of "!", "?", "_", and "." syntax in elixir

! - 如果函數遇到錯誤,將引發異常。

一個很好的例子是Enum.fetch!(它也有一個相同的Enum.fetch,它不會引發異常)。在給定索引處查找元素(從零開始)。如果給定的位置超出集合的範圍,則引發OutOfBoundsError。

+0

謝謝您在SO上查找我一直在尋找的參考資料。我曾希望你所鏈接的內容能夠提供官方文檔的一些參考,但我想它必須這樣做。我來自一個充斥着PEP文章的蟒蛇世界,這裏有不止兩段的文字是爲了「爲什麼」,所以我有點沮喪,沒有相同的公共思維過程,但這會得做。 – Marc

+0

樂意提供幫助,而酏劑也是新的,每天都在改進,包括文件。所以我認爲文檔很快就會達到他們期望的水平。 – coderVishal

+1

我仍然非常感謝您指出的源代碼,然而,現在(回頭看)由於重點放在了函數的雙重版本上,我將@ 0xAX的正確答案移動了。我希望你同意這個決定。 – Marc