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

IEx

IEx - это интерактивная оболочка Elixir - вы можете войти в нее, просто набрав iex в любом терминале. Скорее всего, вы это уже знали, но вот несколько небольших моментов, о которых вы могли не знать.

История Shell

По умолчанию IEx не сохраняет историю между сеансами - это означает, что вы не можете прокручивать назад между тем, что вы, возможно, делали в предыдущих сеансах, с помощью клавиш со стрелками или выполнять поиск в истории с помощью Ctrl-r, как вы могли бы ожидать.

Вы знали, что это можно включить?

Вы можете выполнить его отдельно для каждой оболочки:
iex --erl "-kernel shell_history enabled"

Или вы можете установить его как переменную среды:
export ERL_AFLAGS="-kernel shell_history enabled" для MacOS
set ERL_AFLAGS "-kernel shell_history enabled" для Windows

Помощники

Знаете ли вы о встроенных помощниках IEx? Вот некоторые из самых полезных:

  • h/1 - выводит справку по данному модулю или функции
  • i/1 - выводит информацию о данном термине
  • v/0 - извлекает последнее значение из истории
  • v/1 - извлекает n-е значение из истории
  • recompile/0 - перекомпилирует текущий проект]
  • c/1 - компилирует файл
  • r/1 - перекомпилирует исходный файл данного модуля

Это мои любимые (и те, которые я хочу запомнить), но есть немало еще кое-что, что можно найти в документации.

Разрыв триггера

Вы когда-нибудь набирали многострочное выражение в IEx, пытались выполнить его и замечали, что где-то пропустили закрывающую скобку? Может быть, кавычки?
Если вы нажмете Ctrl-c, вы полностью выйдете из оболочки - похоже, вы застряли, мой друг. Или вы?

#iex:break спешит на помощь. Просто введите это в отдельной строке в IEx, и оно выйдет из любого ожидающего выражения, не разрушая весь сеанс терминала и тест WIP Enum.reduce.

Прай

Были ли вы (или вы) разработчиком Java или Ruby и пропустили контрольные точки? IEx поможет вам: IEx.pry/0 позволяет вам устанавливать точки останова в коде Elixir и «вставлять» в запущенные процессы. Это позволяет вам запустить сеанс IEx внутри данной функции.

Вот пример его использования:

def multiple(arg1, arg2) do
   require IEx; IEx.pry()
   arg1 * arg2
end

Тестирование

- несвежий

Если вы поклонник разработки, основанной на тестировании, вам наверняка захочется узнать о тестировании устаревших файлов с помощью mix.

При первом запуске mix test --stale весь набор тестов будет запущен. Это потому, что технически они все устарели. Однако при последующих запусках будут выполняться только устаревшие тесты.

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

test.watch

mix test.watch - это библиотека с открытым исходным кодом, которая автоматически запускает тесты ваших проектов на Эликсире каждый раз, когда вы сохраняете файл.

Объедините его с такими флагами, как --failed, чтобы по-настоящему разблокировать свой внутренний TDD'er.

test.interactive

Еще одна библиотека с открытым исходным кодом, основанная на вышеупомянутом mix test.watch и интерактивном режиме просмотра Jest, который позволяет вам динамически не менять, какие тесты следует запускать с минимальным нажатием клавиш.

Ваши тесты будут автоматически запускаться при каждом изменении файла - после запуска тестов вы можете использовать p test/my_project/test.exs или любой другой шаблон, чтобы изменить выполняемые тесты.

Ознакомьтесь с документацией для более подробного использования.

Доктесты

Доктесты - это подготовка документации по стероидам. Об этом много говорилось на официальном языке о руководстве по началу работы, но многие разработчики Elixir, с которыми я разговаривал, часто упускали из виду. Доктесты позволяют аннотировать свои функции с помощью примеров использования (включая ожидаемый результат) и запускать их как часть вашего набора тестов.

Взято из руководства по началу работы:

defmodule KVServer.Command do
  @doc ~S"""
  Parses the given `line` into a command.

  ## Examples

      iex> KVServer.Command.parse("CREATE shopping\r\n")
      {:ok, {:create, "shopping"}}

  """
  def parse(_line) do
    :not_implemented
  end
end
# Running the tests...
1) test doc at KVServer.Command.parse/1 (1) (KVServer.CommandTest)
     test/kv_server/command_test.exs:3
     Doctest failed
     code: KVServer.Command.parse "CREATE shopping\r\n" === {:ok, {:create, "shopping"}}
     lhs:  :not_implemented
     stacktrace:
       lib/kv_server/command.ex:7: KVServer.Command (module)

Обновление данных

Встроенный синтаксис обновления

Если вы пишете Elixir, вы собираетесь обновить структуру карты раньше, чем позже - и есть несколько способов сделать это; вы можете использовать Map.put/3 или использовать встроенный синтаксис:

my_data = %{
  foo: 123,
  bar: 456,
  baz: 789
}
# Update my_data
new_data = %{ my_data | foo: 9999 }
# %{ foo: 9999, bar: 456, baz: 789 }

update_in / 3

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

data = %{a: 1, b: 2, c: 3}
update_in(data, [:b, :value], &(&1 * &1))
# %{a: %{value: 1}, b: %{value: 4}, c: %{value: 3}}

update_in/3 чрезвычайно полезен, но остальная часть Kernel полна очень полезных инструментов. Научитесь любить это.

И наконец…

IO.inspect мид-пайп

IO.inspect/2 - это, вероятно, функция, которую я использую чаще всего, когда разрабатываю Elixir, и мне больше всего в ней нравится то, что она возвращает первый переданный ей аргумент: это означает, что вы можете вставить его в середину конвейера, чтобы посмотреть, что именно происходит:

[1, 2, 3]
|> IO.inspect(label: "Original") 
|> Enum.map(&(&1 * &1)) 
|> IO.inspect(label: "Squared")

Присоединиться к команде

Миссия Multiverse - создать разнообразную группу будущих лидеров. Продукты, которые мы создаем, предназначены для того, чтобы связывать кандидатов на стажировку с работодателями и настраивать их на успех на протяжении всей их квалификации. Наша социальная миссия лежит в основе нашего бизнеса, поэтому, если делать добро так же важно для вас, как построение коммерческого бизнеса, вы найдете Multiverse невероятно полезным. У вас также будет возможность применить некоторые из этих замечательных советов ...

Чтобы просмотреть наши последние открытые вакансии, посетите нашу страницу вакансий. Вы также можете прочитать Почему вам следует присоединиться к Multiverse нашего замечательного вице-президента по продукту Эммы ван Дийкум или узнать, как Алекс Драммонд использовал Rust in Elixir для проверки HTML.