Elixir (язык программирования)

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 22:29, 22 января 2016.
Elixir
Класс языка:

мультипарадигмальный: функциональный, параллельный, распределённый, процессо-ориентированный

Появился в:

2012

Автор:

Жозе Валим

Расширение файлов:

.ex, .exs

Выпуск:

1.2.0 (1 January 2016)

Система типов:

динамическая, строгая

Испытал влияние:

Erlang, LFE, Python, Ruby, Clojure

Повлиял на:

LFE

Лицензия:

Apache License 2.0

Сайт:

elixir-lang.org/

Elixir — функциональный, распределённый, язык программирования общего назначения, который работает на виртуальной машине Erlang (BEAM). Elixir построен поверх Erlang, что обеспечивает распределённость, отказоустойчивость, исполнение в режиме мягкого реального времени, метапрограммирование с макросами и полиморфизмом, реализованным через протоколы. Elixir использует Erlang/OTP для работы с деревьями процессов.

История

Elixir был создан Жозе Валимом (José Valim), одним из основных разработчиков Ruby on Rails о со-основателем компании Plataformatec. Его целью было включить более высокую расширяемость и производительность в Erlang VM, сохраняя совместимость с инструментами и экосистемой Erlang.

Возможности

  • Компилируется в байт-код для виртуальной машины Erlang (BEAM)
  • Каждый элемент является выражением
  • Функции языка Erlang могут быть вызваны без влияния на время исполнения из-за компиляции байт-кода в Erlang и наоборот
  • Метапрограммирование дает возможность прямого манипулирования абстрактным синтаксическим деревом (АБС)
  • Полиморфизм, реализованный через механизм протоколов. Как и в Clojure, протоколы обеспечивают механизм диспетчеризации (не стоит путать с множественной диспетчеризацией)
  • Поддержка документации в стиле строк-документации из языка Python (Markdown)
  • Параллельное программирование без разделения ресурсов, через передачу сообщений (модель акторов)
  • Акцентирование на рекурсии и функциях высшего порядка вместо зацикливания, основанного на побочных эффектах
  • Простой параллелизм с использованием механизмов Erlang с упрощенным синтаксисом (например, Task)
  • Ленивые и асинхронные коллекции с потоками
  • Сопоставление с образцом
  • Поддержка Unicode и UTF-8 строк

Сравнение с Erlang

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

Installing

Mac OS X

  • Homebrew
    • Обновите Hombrew: brew update
    • Выполните: brew install elixir
  • Macports
    • Выполните: sudo port install elixir

Unix

  • Arch Linux (Community repo)
    • Выполните: pacman -S elixir
  • openSUSE (и SLES 11 SP3+)
    • Добавьте devel репозиторий Erlang: zypper ar -f obs://devel:languages:erlang/ erlang
    • Выполните: zypper in elixir
  • Gentoo
    • Выполните: emerge --ask dev-lang/elixir
  • Fedora 17 и новее
    • Выполните: yum install elixir
  • Fedora 22 и новее
    • Выполните: dnf install elixir
  • FreeBSD
    • Через ports: cd /usr/ports/lang/elixir && make install clean
    • Через pkg: pkg install elixir
  • Ubuntu 12.04 и 14.04 / Debian 7
    • Добавьте репозиторий Erlang Solutions: wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb && sudo dpkg -i erlang-solutions_1.0_all.deb
    • Выполните: sudo apt-get update
    • Установите платформу Erlang/OTP и все её приложения: sudo apt-get install esl-erlang
    • Установите Elixir: sudo apt-get install elixir

Windows

  • Веб-установщик
    • Скачайте установщик
    • Следуйте указанием мастера установки
  • Chocolatey
    • cinst elixir

Прекомпилированный пакет

Elixir предоставляют прекомилированные пакеты каждого релиза. Сначала установите Erlang, потом скачайте и разархивируйте Precompiled.zip файл последнего релиза.

После распаковки релиза, вы можете выполнить команды elixir и iex, находясь в директории bin, но рекомендуется добавить путь до Elixir bin в переменную окружения PATH для упрощения разработки.

Установки Erlang

Единственной зависимость для Elixir является Erlang версии 18.0 и выше. Его можно установить при помощи прекомпилированного пакета. Если вы хотите скомпилировать его сами, используйте исходный код, который можно найти на сайте Erlang или следуйте инструкции из документации Riak

Для пользователей Windows рекомендуется использовать прекомпилированные пакеты.

После установки Erlang, следует открыть командную строку и проверить работоспособность Erlang, запросив его версию через команду erl. Будет выведена подобная информация:

 Erlang/OTP 18 (erts-7) [64-bit] [smp:2:2] [async-threads:0] [hipe] [kernel-poll:false]

Обратите внимание, что после установки, исполняемые файлы Erlang не будут доступны в переменной окружения PATH. Удостоверьтесь, что они прописаны в PATH, иначе Elixir не будет работать.

Setting PATH environment variable

Рекомендуется добавить путь до bin Elixir в переменную окружения PATH для упрощения разработки.

Инструкция для Windows, объясняющая процесс.

В Unix системах необходимо найти файл профиля shell и добавить в конец файла следующую страку, указывающую путь к Elixir:

export PATH="$PATH:/path/to/elixir/bin"


Синтаксис и семантика

Базовые типы

  • Числа
3    # целое
0x1F # целое
3.0  # вещественное
  • Атомы
:hello # атом
  • Кортежи
{1,2,3} # кортеж

Доступ к элементу можно получить при помощи функции `elem`:

elem({1, 2, 3}, 0) #=> 1
  • Списки
[1,2,3] # список

Получить доступ к голове и хвосту списка можно следующим способом:

[head | tail] = [1,2,3]
head #=> 1
tail #=> [2,3]
  • Двоичные
<<1,2,3>> # двоичные
  • Strings и char lists
"hello" # string
'hello' # char list
  • Многострочность
"""
I'm a multi-line
string.
"""
#=> "I'm a multi-line\nstring.\n"

Операторы

  • Немного математики
1 + 1  #=> 2
10 - 5 #=> 5
5 * 2  #=> 10
10 / 2 #=> 5.0
  • Оператор `/` в Elixir всегда возвращает вещественное число.
  • Для целочисленного деление используется `div`
div(10, 2) #=> 5
  • Для получения остатка от деления используется `rem`
rem(10, 3) #=> 1
  • Также существуют логические операторы: `or`, `и` и `not`. Они принимают булевское значение первым аргументом.
true and true #=> true
false or true #=> true
# 1 и true    #=> ** (ArgumentError) ошибка аргумента
  • Elixir также предоставляет операторы `||`, `&&` и `!` которые принимают аргументы любого типа. Любое значение кроме `false` и `nil` принимается за true.
1 || true  #=> 1
false && 1 #=> false
nil && 20  #=> nil
!true #=> false
  • Операторы сравнения: `==`, `!=`, `===`, `!==`, `<=`, `>=`, `<` и `>`
1 == 1 #=> true
1 != 1 #=> false
1 < 2  #=> true
  • `===` и `!==` более строго сравнивают целые и вещественные:
1 == 1.0  #=> true
1 === 1.0 #=> false
  • Возможно сравнение двух разных типов:
1 < :hello #=> true

Общий порядок сортировки следующий: number < atom < reference < functions < port < pid < tuple < list < bit string

Управление потоком

  • выражение `if`
if false do
  "This will never be seen"
else
  "This will"
end
  • выражение `unless`
unless true do
  "This will never be seen"
else
  "This will"
end
  • `case` позволяет сравнивать значение с несколькими шаблонами:
case {:one, :two} do
  {:four, :five} ->
    "This won't match"
  {:one, x} ->
    "This will match and bind `x` to `:two`"
  _ ->
    "This will match any value"
end
  • Принято связывать не используемое значение с `_`. Например, если для нас важна только голова:
[head | _] = [1,2,3]
head #=> 1
  • Для улучшения читаемости применяется следующее:
[head | _tail] = [:a, :b, :c]
head #=> :a
  • `cond` позволяет проверять несколько условий одновременно.
cond do
  1 + 1 == 3 ->
    "I will never be seen"
  2 * 5 == 12 ->
    "Me neither"
  1 + 2 == 3 ->
    "But I will"
end

Принято назначать последнее условие равным `true`, чтобы оно срабатывало всегда.

cond do
  1 + 1 == 3 ->
    "I will never be seen"
  2 * 5 == 12 ->
    "Me neither"
  true ->
    "But I will (this is essentially an else)"
end
  • `try/catch` используется чтобы ловить брошеные значения, также поддерживается пункт `after`, вызываемый вне зависимости от того, поймано ли значение или нет.
try do
  throw(:hello)
catch
  message -> "Got #{message}."
after
  IO.puts("I'm the after clause.")
end
#=> I'm the after clause
# "Got :hello"

Книги по теме

  • Programming Elixir от Dave Thomas
  • Elixir in Action от Saša Jurić
  • Introducing Elixir от Simon St. Laurent, J. David Eisenberg
  • The Little Elixir and OTP Guidebook от Benjamin Tan Wei Hao
  • Elixir Cookbook от Paulo A Pereira

Скринкасты

Смотрите также

Домашняя страница Elixir
Неофициальная документация
Elixir на Github
Elixir в Twitter

Ссылки

Официальная документация
Статья "Learn X in Y minutes"
Страница в Википедии