Elixir
Erlang является уникальной по своим возможностям платформой, и не смотря на это, язык до сих пор является экзотикой. Причин существует несколько. Например, тугая арифметика, непривычность синтаксиса, функциональность. Это не недостатки. Это просто вещи, с которыми большинство программистов не могут или не хотят работать.
Несколько дней назад Jose Valim опубликовал в своем репозитории проект языка, построенного поверх Erlang. Этот язык обладает простой объектной моделью и Ruby-подобным синтаксисом. Под катом выжимки из документации и видео, демонстрирующее простой пример.
disclaimer: %username%, прежде чем делать выводы насчет того, что умеет, а что не умеет elixir, просьба глазами пройтись хотя бы по readme.
Elixir — язык программирования, работающий поверх Erlang. Как Erlang, это — функциональный язык со строгими вычислениями, однократным присвоением и динамической типизацией, созданный, чтобы поддерживать распределенные, отказоустойчивые, безостановочные приложения с горячей заменой кода. Elixir позволяет Вам вызывать модули Erlang без необходимости преобразовать типы данных, поэтому нет никакой потери в производительности при вызове кода Erlang.
Основное различие между Elixir и Erlang — синтаксис и объектная ориентированность. Elixir обеспечивает очень простую объектную модель и синтаксис, большей частью основанный на Ruby.
В настоящее время главной задачей является разработка стандартной библиотеки. Большая часть существующей стандартной библиотеки написана на самом Elixir, и Вам не нужно знать Erlang, чтобы внести свой вклад в ее развитие. Достаточно будет знакомства с принципами OTP.
Чтобы начать работу, для начала нужно клонировать репозиторий к себе на компьютер, скомпилировать и проверить его:
$ git clone https://github.com/josevalim/elixir.git $ cd elixir $ make test $ bin/elixir -v Elixir 0.1.0
Комментарии в Elixir, как и в Erlang, обозначаются через “%”:
% This is a commented line
Далее, “% =>” показывают значение выражения:
1 + 1 % => 2
Elixir поддерживает целые и дробные числа:
2 + 15 % => 17 - 13 * 10 % => -130 1986 - 1985 % => 1 5 / 2 % => 2.5 4 / 2 % => 2.0
Как в Ruby, любая конструкция является объектом. Мы можем вызывать методы у чисел:
-1.abs % => 1 5.div(2) % => 2 %surprise ! 1.+(2) % => 3
Атомы в Elixir называются Symbols (как в Ruby). Но синтиксис позаимствован у Lisp (Jose объяснил это в твиттере тем, что хочет «:» использовать в словарях):
'atom 'Atom 'atom_without_spaces '"Atom with Spaces"
Списки являются наиболее полезной структурой в Elixir (как и в любом другом функциональном языке), могу содержать все, что угодно и имеют набор методов:
% Some list with elements ['atom, 1, 2, 3, < 'some, 'tuple >] % An empty list [] [1, 2, 3].length % => 3 ['a, 'b, 'c][1] % => 'b [1, 2, 3] + [4, 5, 6] % => [1,2,3,4,5,6]
Списки в Erlang и Elixir реализованы как связные списки, поэтому предварительное добавление элементов происходит намного быстрее, чем последующее:
list = [2,3,4] % Don't do this: [1] + [2,3,4] % => [1,2,3,4] [0,1] + [2,3,4] % => [0,1,2,3,4] % Do this instead: [1|list] % => [1,2,3,4] [0,1|list] % => [0,1,2,3,4]
Настоящую силу списков получаешь, когда используешь их вместе с функциями
[1, 2, 3].map do (x) x * 2 end % => [2, 4, 6] [1, 2, 3].foldl 0, do (x, acc) acc + x end % => 6
Строки в Erlang представлены списком символов:
"hello" == [104, 101, 108, 108, 111]
Это накладно, поскольку каждый символ занимает 8 байт памяти (не бит!). Elixir реализует строки, в виде utf8 бинарных строк:
% The famous "hello world" string "hello world" % A string converted to its underlying binary: "hello".to_bin % => <<[104, 101, 108, 108, 111]>> % A string converted to a char list: "hello".to_char_list % => [104, 101, 108, 108, 111] % Strings are UTF-8 "Arrow ⇧ up".length % => 10
Это существенное изменение. Строки являются единственными объектами, требующими преобразования:
% Converting a string_from_erlang to Elixir's String String.new string_from_erlang % Where string_from_erlang is either a binary: <<[104, 101, 108, 108, 111]>> % Or a char_list: [104, 101, 108, 108, 111] % Converting a string_from_elixir to Erlang "string_from_elixir".to_bin "string_from_elixir".to_char_list
Наконец, строки поддерживают интерполяцию:
"string # interpolation" % => "string with interpolation" "1 + 1 = #" % => "1 + 1 = 2"
Функции являются важной частью Elixir, как и любого другого функционального языка. Функции можно создавать с помощью «do» или «->»:
my_function = do 1 + 2 end my_function() % => 3 another_function = -> 1 * 2 end another_function() % => 2
Как и Erlang, Elixir поддерживает Pattern matching и единичное присваивание.
% Let's bound the variable x to 'foo x = 'foo % Now let's match a tuple with other tuple. % Since x is already bound, we are comparing x with 'baz and it will fail: < x, y >= < 'baz, 'bar >% In this case, we compare 'x with 'foo and it matches. % Since y is unbound, we assign 'bar to it: < x, y >= < 'foo, 'bar >x % => 'foo y % => 'bar [h|t] = [1,2,3] h % => 1 t % => [2,3] % Raises an error because h was already assigned to 1 and 1 does not match 2 [h|t1] = [2,3,4]
Как и в Eralng, pattern matching используется в сигнатурах функций:
module Math def fibonacci(0) 0 end def fibonacci(1) 1 end def fibonacci(n) fibonacci(n - 1) + fibonacci(n - 2) end end Math.fibonacci(0) % => 0 Math.fibonacci(1) % => 1 Math.fibonacci(3) % => 2 Math.fibonacci(10) % => 55
Вызов методов Erlang весьма тривиален:
% Accessing the is_atom BIF from Erlang. % This is the same as `is_atom(foo)` in Erlang. Erlang.is_atom('foo) % => true % Accessing the function delete from module lists. % This is the same as `lists:member(1, [1,2,3])` in Erlang. Erlang.lists.member(1, [1,2,3]) % => true
- Динамический выбор реализации — когда вызывается метод, объект сам выбирает, какой код выполнить
- Mixin’ы — объекты не содержат методов. Все методы запакованы в модули, которые подмешиваются в объекты.
- Инкапсуляция — методы могут быть public, protected или private.
- Открытая рекурсия — объекты имеют специальную переменную self, которая позволяет вызвать другие методы объекта не затрагивая цепочку вызовов.
- Рефлексия — Elixir способен просматривать и модифицировать структуру объекта во времени исполнения.
object Person def constructor(name, age) < 'name: name, 'age: age >end def name @name end def age @age end def name(value) self.set_ivar('name, value) end end person = Person.name('john, 24) another_person = person.name('john_doe) person.name % => 'john person.age % => 24 another_person.name % => 'johh_doe another_person.age % => 24
Это описание малой части возможностей Elixir. В репозитории опубликована отличная обзорная документация. Ролик ниже иллюстрирует небольшой пример работы языка:
Elixir: Привет, Мир!
Elixir – динамический, функциональный язык программирования, спроектированный для создания масштабируемых и легко поддерживаемых приложений. Эликсир был выпущен в 2012 году Жозе Валимом, и несколько лет поддерживался только своим создателем. В какой-то момент его популярность выросла настолько, что многие компании начали серьезно использовать его в своих проектах.
Эликсир работает поверх виртуальной машины языка эрланг. Она широко известна своими уникальными возможностями для создания отказоустойчивых и распределенных систем. Причем, как во встраиваемых устройствах, например роутерах, так и в вебе, при создании приложений реального времени (игры, мессенджеры).
Практически все, что говорится про эликсир, является заслугой виртуальной машины эрланга. Эликсир задумывался как язык, который привносит в мир эрланга кое-что новое, чего не хватало самому эрлангу. В первую очередь это средства, повышающие уровень абстракции (Struct, Protocol), позволяющие писать более лаконичный код (оператор pipe, конструкция with), и удобно управлять проектом и его зависимостями (mix). Кроме того, это метапрограммирование — мощная система макросов, позволяющая создавать DSL-языки. Хорошим примером такого DSL-языка является библиотека Ecto для работы с базами данных.
Эликсир – практичный язык. Он прост в освоении и эффективен в работе. На его базе создан веб-фреймворк Phoenix, очень напоминающий упрощенный Ruby On Rails. Его код открыт и доступен на гитхабе. Было бы несправедливо не сделать обучение по Elixir именно тут)
Задание
Наберите в редакторе код из задания символ в символ и нажмите «Проверить».
# Определение модуля Solution defmodule Solution do # Определение функции hello # Отступ 2 пробела def hello do # Вызов функции другого модуля # Отступ 2 пробела IO.puts("Hello, World!") # В конце не нужна точка с запятой end end
Упражнение не проходит проверку — что делать?
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
- Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Мой код отличается от решения учителя
Это нормально , в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Прочитал урок — ничего не понятно
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Полезное
- repl.it — здесь вы можете экспериментировать с кодом на Elixir.
- Официальный сайт
- Phoenix, веб-фреймворк
- Исходный код языка
- Официальный форум, посвященный языку
Основы
Инструкции по установке для всех ОС есть на официальном сайте.
После того, как Elixir установлен, вы с лёгкостью можете проверить, какая именно версия была установлена.
% elixir -v Erlang/OTP > [erts->] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace] Elixir >
Интерактивный режим
Вместе с языком в комплекте идет приложение интерактивной командной строки IEx, которое позволяет выполнять выражения языка на лету.
Для того чтобы начать, запустите iex :
Erlang/OTP > [erts->] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace] Interactive Elixir (>) - press Ctrl+C to exit (type h() ENTER for help) iex>
Примечание: В Windows PowerShell вам нужно написать iex.bat .
Попробуем написать несколько простых выражений:
iex> 2+3 5 iex> 2+3 == 5 true iex> String.length("The quick brown fox jumps over the lazy dog") 43
Не стоит волноваться, если пока вы поняли не все выражения.
Базовые типы
Целые числа
iex> 255 255
Поддерживаются также бинарные, восьмеричные и шестнадцатеричные числа:
iex> 0b0110 6 iex> 0o644 420 iex> 0x1F 31
Числа с плавающей запятой
В Elixir числа с плавающей запятой требуют наличия хотя бы одной цифры перед точкой. Также они поддерживают e для описания экспонентной части:
iex> 3.14 3.14 iex> .14 ** (SyntaxError) iex:2: syntax error before: '.' iex> 1.0e-10 1.0e-10
Логический тип
Elixir поддерживает два значения логического типа: true и false . Абсолютно все значения в языке считаются истинными кроме false и nil :
iex> true true iex> false false
Атомы
Атом — константа, название которой является и значением. В других языках (например, в Ruby) они называются символами:
iex> :foo :foo iex> :foo == :bar false
Стоит отметить, что булевы значения true , false являются атомами :true и :false .
iex> is_atom(true) true iex> is_boolean(:true) true iex> :true === true true
Названия модулей в Elixir — тоже атомы. MyApp.MyModule — валидный атом, даже если такой модуль ещё не был объявлен.
iex> is_atom(MyApp.MyModule) true
Также атомы используются в качестве ссылок на модули из библиотек Erlang, в том числе и встроенные.
iex> :crypto.strong_rand_bytes 3 23, 104, 108>>
Строки
Строки в Elixir всегда представлены в кодировке UTF-8 и заключаются в двойные кавычки:
iex> "Hello" "Hello" iex> "dziękuję" "dziękuję"
Строки могут включать разрывы и экранированные последовательности:
iex> "foo . > bar" "foo\nbar" iex> "foo\nbar" "foo\nbar"
В Elixir есть и более сложные типы данных. Мы узнаем о них больше, когда познакомимся с коллекциями и функциями.
Базовые операторы
Арифметика
В Elixir, ожидаемо, есть базовые операторы + , — , * , / . Стоит отметить что результатом вызова / всегда будет число с плавающей запятой:
iex> 2 + 2 4 iex> 2 - 1 1 iex> 2 * 5 10 iex> 10 / 5 2.0
Если нужно целочисленное деление или получение остатка — в языке есть две удобные функции специально для этого:
iex> div(10, 5) 2 iex> rem(10, 3) 1
Логические операторы
Elixir предоставляет операторы || , && , ! , которые поддерживают работу с любыми типами:
iex> -20 || true -20 iex> false || 42 42 iex> 42 && true true iex> 42 && nil nil iex> !42 false iex> !false true
Также есть три дополнительных оператора, у которых первый аргумент обязан быть логического типа ( true или false ):
iex> true and 42 42 iex> false or true true iex> not false true iex> 42 and true ** (ArgumentError) argument error: 42 iex> not 42 ** (ArgumentError) argument error
Примечание: операторы and и or в Elixir на самом деле соответствуют andalso и orelse в Erlang.
Сравнения
В Elixir поддерживаются все стандартные операторы сравнения: == , != , === , !== , = , < , >.
iex> 1 > 2 false iex> 1 != 2 true iex> 2 == 2 true iex> 2 3 true
Для строгого сравнения целых чисел и чисел с плавающей запятой используется === :
iex> 2 == 2.0 true iex> 2 === 2.0 false
Удобной возможностью языка является то, что любые типы сравнимы друг с другом. Это удобно при сортировках. Порядок не стоит запоминать, но о его существовании стоит знать:
number atom reference function port pid tuple map list bitstring
Это приводит к некоторым интересным правильным сравнениям, которых обычно нет в других языках программирования:
iex> :hello > 999 true iex> :hello, :world> > [1, 2, 3] false
Интерполяция строк
Если вы использовали язык Ruby, то интерполяция в Elixir покажется вам знакомой:
iex> name = "Sean" iex> "Hello #name>" "Hello Sean"
Объединение строк
Для объединения двух строк используется оператор <> :
iex> name = "Sean" iex> "Hello " <> name "Hello Sean"
Бесплатный курс по Elixir
Эликсир — язык программирования, работающий поверх Erlang. Как Erlang, это — функциональный язык со строгими вычислениями, однократным присвоением и динамической типизацией, созданный, чтобы поддерживать распределенные, отказоустойчивые, безостановочные приложения с горячей заменой кода
14 часов 2077 студентов 49 уроков с практикой в браузере
Основы Elixir
- 1. Привет, Мир!
- 2. Модули
- 3. Функции в Elixir
- 4. Строки
- 5. Арифметика
- 6. Логика
- 7. Атрибуты
- 8. Интероп с Erlang
- 9. Строковые метки (сигили)
Язык Эликсир необычный, большинство его элементов устроены сложнее, чем кажется на первый взгляд. В первом модуле мы рассмотрим модули и функции, базовые типы данных и операции над ними.
Типы данных Elixir
- 10. Атомы и кортежи
- 11. Списки
- 12. Словари
Во втором модуле мы продолжим знакомство с разными типами данных: с атомами, кортежами, списками и словарями. Если вы не знакомы с функциональным программированием, то уже на этом этапе что-то может показаться странным. Но не пугайтесь, использовать все это не сложно.
Управляющие конструкции в Elixir
- 13. Сопоставление с образцом (Pattern Matching)
- 14. Сопоставление с образцом для словарей
- 15. Конструкция case
- 16. Конструкция cond
- 17. Тело функции (function clause)
- 18. Оператор pipe
В третьем модуле мы научимся управлять ветвлениями в коде — вызывать ту или иную ветку кода в зависимости от некоторых условий. Тут мы познакомимся с killer feature функционального программирования — сопоставлением с образцом (pattern matching).
Основы функционального программирования
- 19. Рекурсия
- 20. Рекурсивные функции с аккумуляторами
- 21. Неизменяемые структуры данных
- 22. Анонимные функции
Эликсир — яркий представитель семейства функциональных языков. Пришло время узнать, что такое функциональное программирование, из каких элементов оно состоит, и чем отличается от других парадигм программирования. Мы уже познакомились с одним из важнейших элементов ФП — сопоставлением с образцом. Теперь рассмотрим другие элементы: иммутабельность, рекурсию, функции высшего порядка и анонимные функции.
Работа с коллекциями в Elixir
- 23. Отображение
- 24. Фильтрация
- 25. Свертка
- 26. Компрехеншен или конструкторы списков
- 27. Стримы
В этом модуле мы изучим типовые способы работы со списками и другими коллекциями: map, filter и reduce. Познакомимся с модулем `Enum` — рабочей лошадкой для всех коллекций. Также изучим конструкторы списков (lists comprehension) и стримы (streams).