Эликсир, аргумент списка ключевых слов по умолчанию

В elixir можно использовать аргументы по умолчанию в определениях функций, но я обнаружил, что это невозможно сделать с аргументами из одного списка ключевых слов, такими как:

def do_stuff(
  success: sucess \\ fn(conn) -> conn end,
  error: error
) do
  # ...
end

Кроме того, я думал о том, чтобы избежать такого стиля кодирования с «передачей обратных вызовов», используя что-то вроде обещаний JS, но я не смог найти реализацию обещаний для Elixir.

Может быть, прямо в язык встроено что-то, что помогло бы мне писать лучший код и приблизиться к стандартам эликсира.

Основной вопрос: можно ли использовать аргументы ключевых слов по умолчанию?

Дополнительный вопрос: есть ли что-то, что Эликсир предлагает, чтобы помочь избежать этого стиля программирования с "передачей обратных вызовов" в пользу более реактивного/составного механизма?


person nicooga    schedule 15.05.2016    source источник


Ответы (1)


Нет, невозможно использовать аргументы ключевых слов по умолчанию, поскольку аргументы ключевых слов — это просто синтаксический сахар для одного списка ключевых слов:

do_stuff(success: ..., failure: ...)

такой же как

do_stuff([success: ..., failure: ...])

Таким образом, список ключевых слов — это всего лишь один аргумент. В определении функции вы выполняете сопоставление со списком ключевых слов, переданным в do_stuff/1: обязательно следите за этим, поскольку определение вашей функции не будет соответствовать, если порядок ключевых слов будет не то же самое (т.е. do_stuff(failure: ..., success: ...)).

Я думаю, что хороший способ преодолеть это — просто использовать два разных аргумента для функции do_stuff:

def do_stuff(success \\ fn(conn) -> conn end, failure \\ fn(err) -> err end)

Таким образом, аргументы по умолчанию работают так, как ожидалось. Если вам действительно нужно, чтобы ваш аргумент был списком ключевых слов, вы можете обрабатывать значения по умолчанию внутри тела функции:

def do_stuff(options) do
  success = options[:success] || (fn(conn) -> conn end)
  failure = options[:failure] || (fn(err) -> err end)
end

Наконец, что касается «стиля обратного вызова», о котором вы упомянули, я не знаю ничего, что работало бы иначе, чем просто передача fn, когда что-то делается, если только вы не начнете изучать параллелизм и передачу сообщений.

person whatyouhide    schedule 15.05.2016