2015-10-24 6 views
18

я первым заметил функцию с задней восклицательный-балльной/челки (!), Проходя через учебник Phoenix (в разделе Incoming Events)Что такое функции взрыва эликсира?

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

Спасибо, что нашли время, чтобы предоставить хороший пример из источника Феникса. Он отлично отвечает на мой вопрос. Я застрял между вашим ответом и тем, что я выбрал, потому что оба хорошо объяснили мой вопрос. Я решил не выбирать этот только потому, что он сосредоточился на использовании Феникса '!' И, к сожалению, не выраженный в моем вопросе, меня интересуют соглашения Эликсира несколько больше, чем Феникс. – Marc

+1

Я собираюсь есть свои собственные слова - и принимаю ваш ответ, потому что он указывает на важную деталь, о которой упоминается @MoxleyStratton - «Соглашение о запрете применяется к ситуациям, в которых есть две версии функции - одна, которая вызывает исключение (версия бэнга), а другая - нет. " – Marc

2

Вы в основном получили это право Марка - это условность сказать НЕ ПОДНЯТЬ ОШИБКА, если все пойдет не так.

Существует документация, в своем роде, на этом page, что переговоры о доступе файла (прокрутите вниз до фразы задних взрыва)

+0

Моя основная проблема заключается в том, что документация выполняется мимоходом, и мы, как сообщество эликсиров, как ожидается, поймаем тонкости. Я рад, что смог кое-что понять и что вы предоставили «документацию сообщества» о его приемлемом использовании :) TY – Marc

+0

Я считаю, что этот ответ вводит в заблуждение. Прочитав это, разработчик мог прийти к выводу, что при создании функции, которая вызывает ошибку, ее следует назвать с помощью bang (!). Это не намерение съезда. @ 0xAX понял, что, видя функцию взрыва, «это означает, что, вероятно, есть функция с тем же именем, но без символа». Соглашение о банде применяется к ситуациям, в которых есть две версии функции - одна, которая вызывает исключение (версия bang), а другая - нет. –

+0

@MoxleyStratton оглядываясь назад на этот вопрос (и принятый ответ) Я согласен с вами (и не согласен с моим прошлым решением). – Marc

11

его просто именования. Ответьте на этот ответ - What's the meaning of "!", "?", "_", and "." syntax in elixir

! - Возбудет исключение, если функция встретит ошибку.

Одним хорошим примером является Enum.fetch! (Он также имеет ту же Enum.fetch, которая не вызывает исключения).Находит элемент по заданному индексу (на основе нуля). Повышает OutOfBoundsError, если данная позиция находится вне диапазона коллекции.

+0

Спасибо, что нашли ссылку, которую я искал здесь, на SO. Я надеялся, что то, что вы связали, будет иметь некоторые ссылки на официальную документацию, но я думаю, что это нужно будет сделать. Я исхожу из мира python, полного статей PEP, и там, где более чем пара параграфов посвящена «почему», поэтому я немного разочарован тем, что тот же процесс общественного обсуждения недоступен, но это будет нужно сделать. – Marc

+0

рад помочь, а также эликсир является новым и улучшает каждый день, включая документацию. Поэтому я думаю, что документы скоро достигнут того уровня, который их ожидает. – coderVishal

+1

Я все еще очень благодарен за источник, которого вы указали, однако теперь (оглядываясь назад) Я переместил правильный ответ на @ 0xAX из-за того, что акцент сделан на двойных версиях функции. Надеюсь, вы согласны с этим решением. – Marc

Смежные вопросы