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

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

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

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

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

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

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

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 когда что-то сделано, если только вы не начинаете изучать параллелизм и передачу сообщений.

Другие вопросы по тегам