avva: (Default)
[personal profile] avva
Прочитал книгу Джо Армстронга про Эрланг. Теперь подмывает что-нибудь на нем написать.

Очень стройный, интересный и гармоничный язык.

Если прыгать по ключевым словам, то Эрланг:

- функциональный язык, но с вполне обычной императивной семантикой исполнения
- компилируется в байткод и выполняется в виртуальной машине, с очень удобной интерактивной средой (как Лисп)
- динамические типы (с опциональной статической аннотацией)
- immutable state, переменные получают значение один раз и больше его не меняют
- pattern-matching как в Хаскеле или даже круче, list comprehension как в Питоне
- типичная программа состоит из множества очень легких "процессов", которые выполняются одновременно, не имеют между собой общей памяти, общаются путем явной передачи сообщений
- эти процессы с одинаковой легкостью могут быть внутри одной виртуальной машины или в нескольких разных или во многих на разных серверах, в их общении при этом ничего не меняется, следовательно: scaling up, fault tolerance, multicore programming - все это делать легко и приятно

Что мне особенно нравится: интерактивная среда. Удобнейший pattern-matching в заголовках функций. Подход Эрланга к обработке ошибок (подход let it crash на любую непредвиденную ошибку: пусть процесс падает, другие это заметят, запишут в лог, перезапустят). Удобный синтаксис для работы с отдельными битами в памяти.

Что мне не нравится: работа со строками, кажется, утомительна и многословна. Циклы на коленке через хвостовую рекурсию уже не вставляют. Отсутствие настоящих статических типов играет, вероятно, свою роль в достаточно объемных проектах.

Книга отлично написана, очень рекомендую. Для знакомства с языком достаточно прочитать первую половину (первые три части), а также главы 24 и 26, где описаны важные принципы построения программ из процессов. Остальные 50% - подробное знакомство с некоторыми стандартными библиотеками, и несколько обширных примеров кода - можно пропустить или быстро пролистать.

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

Date: 2014-04-16 05:53 pm (UTC)
From: [identity profile] zelych.livejournal.com
А можно немножко подробнее про "pattern-matching как в Хаскеле или даже круче"?
Edit: т.е. чем он круче?
Edited Date: 2014-04-16 05:53 pm (UTC)

Date: 2014-04-16 06:09 pm (UTC)
From: [identity profile] avva.livejournal.com
Наверное, про "даже круче" я несколько преувеличил (перечитал сейчас, что есть в Хаскеле). Мне понравилось, во-первых, что в Эрланге можно весь паттерн или часть его присвоить переменной. Я вижу, что это есть в Хаскеле в виде "as pattern", но кажется, только для всего паттерна, а не его части. Т.е. что-то вроде

f ( {First, Second, Pair={Third, Fourth}} ) ->

в Хаскеле так легко не делается?

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

Date: 2014-04-16 06:19 pm (UTC)
From: [identity profile] zelych.livejournal.com
Часть паттерна можно присвоить переменной:
    > let f all@(first@(x:xs), second@(y:ys)) = print (all, first, second)
    > f ([1],[2])
    (([1],[2]),[1],[2])
Что в последнем абзаце написано я не понимаю, поэтому хаскельного аналога предложить не могу.

Btw, спасибо за рецензию, я почему-то сразу же купил книжку.
Edited Date: 2014-04-16 06:20 pm (UTC)

Date: 2014-04-16 06:25 pm (UTC)
From: [identity profile] avva.livejournal.com
ага, понял, спасибо.

Последний абзац:

f(X,Y,Z) when X > 0, Y < Z ; X < -5, Y+Z > X -> ...

эквивалентно, если я правильно помню синтаксис Хаскеля

f x y z
| (x>0 && y<z) || (x<-5 && y=z>x) = ...

В общем, это мелочь и я даже и не знаю, назвать ли это преимуществом.


Edited Date: 2014-04-16 06:25 pm (UTC)

Date: 2014-04-16 06:29 pm (UTC)
From: [identity profile] zelych.livejournal.com
Ясно.
Действительно, в эрланге более читаемо получается.
Синтаксис верный.

Date: 2014-04-16 07:33 pm (UTC)
From: [identity profile] migmit.livejournal.com
В Хаскеле, как уже написали, это делается легче.

А в гардах нельзя использовать собственные функции:
is_result({ok, A}) -> is_atom(A);
is_result({ok, A, B}) -> is_string(A) andalso is_number(B);
is_result(_) -> false.
...
case ... of
  Result when is_result(Result) -> ...

Поэтому приходится извращаться с препроцессором
-define(is_result(R),
 (is_tuple(R),
  (size(R) =:= 2, is_atom(element(2, R));
   size(R) =:= 3, is_string(element(2, R)), is_number(element(3, R))),
  element(1, R) =:= ok))
...
case ... of
  Result when ?is_result(Result) -> ...

Как обычно, препроцессор помогает героически преодолеть слабость языка.
Edited Date: 2014-04-16 07:34 pm (UTC)

Date: 2014-04-16 10:03 pm (UTC)
From: [identity profile] avva.livejournal.com
Да, это лажа, согласен. Потому что нет функциональной чистоты; но могли бы по идее постараться посильнее и доказать в компиляторе, что предложенная собственная функция действительно не имеет побочных эффектов.

Date: 2014-04-17 04:55 am (UTC)
From: [identity profile] migmit.livejournal.com
Проблема несколько шире. Скажем, функция mnesia:transaction/1 хочет, чтобы переданный ей аргумент был функцией, имеющей (возможно) некоторые сайд-эффекты, но только такие, которые происходят из обращений к mnesia. Это тоже в компиляторе доказывать? Но компилятор знать не знает о существовании mnesia.

Date: 2014-04-17 08:49 am (UTC)
From: [identity profile] janatem.livejournal.com
Насколько я понял эту ветвь дискуссии, паттерны Эрланга не мощнее чем в Хаскеле, так?

Насчет присвоения паттера переменной мне вспомнилась одна идея, которая, как мне кажется ни в одном языке не была реализована. А именно, почему бы не дать возможность поименовать сам паттерн? Не поматчить паттерн или его часть на переменную (что обычно делается с помощью as), а именно ввести имя — синоним данного паттерна, против которого (имени) можно матчить выражения (как по-русски сказать to match [expression] against [pattern]?). Когда я программировал на SML, меня удивил запрет на использование идентификаторов, начинающихся с подчеркивания, и заподозрил, что они зарезервированы именно для этого, ведь один такой идентификатор, играющий роль паттерна, уже есть (во всех языках) — это просто подчеркивание. Хотя доказательств этому не нашел.

Осталось ввести новое ключевое слово pat, служащее для декларации новых паттернов, которое у меня получилось в ML-ном стиле; для единообразия остальные синтаксические элементы пишу в том же стиле.
pat _nempty = _::_

Или, вот (бесполезный) синоним универсального паттерна:
pat _underscore = _

Потом пользоваться им:

fun f Nil = e1
f _nempty = e2

Разумеется, у паттернов должны быть свободные переменные, который потом будут означиваться при матчинге:

pat _singleton x = [x]
pat _tail x = _::x
Edited Date: 2014-04-17 08:50 am (UTC)

Date: 2014-04-17 08:56 am (UTC)
From: [identity profile] avva.livejournal.com
Насколько я понял эту ветвь дискуссии, паттерны Эрланга не мощнее чем в Хаскеле, так?

Да.

Date: 2014-04-17 09:52 am (UTC)
From: [identity profile] zelych.livejournal.com
В хаскеле есть что-то похожее.
PatternGuards (http://www.haskell.org/ghc/docs/7.6.3/html/users_guide/syntax-extns.html#pattern-guards) или ViewPatterns (http://www.haskell.org/ghc/docs/7.6.3/html/users_guide/syntax-extns.html#view-patterns)
    ghci> :set -XViewPatterns 
    ghci> :set -XLambdaCase 
    ghci> let pat_nempty = \case { _:_ -> Just () ; _ -> Nothing}
    ghci> let f (pat_nempty -> Just _) = "it's almost full!"
    ghci> f []
    "*** Exception: :5:5-50: Non-exhaustive patterns in function f
    ghci> f [2]
    "it's almost full!"

    ghci> let pat_singleton x = \case {[y] | x == y -> Just x ; _ -> Nothing}
    ghci> let g (pat_singleton 3 -> Just _) = "three of them"
    ghci> :{
    ghci| let g (pat_singleton 3 -> Just _) = "three of them"
    ghci|     g _ = "don't know"
    ghci| :}
    ghci> g [2]
    "don't know"
    ghci> g [3]
    "three of them"
    ghci> g [3,4]
    "don't know"

Можно даже PatternView передавать в функцию в качестве аргумента:
    example :: (String -> Integer) -> String -> Bool
    example f (f -> 4) = True

Правда PatternViews я в реальном коде не встречал ни разу.

Date: 2014-04-17 11:22 am (UTC)
From: [identity profile] thesz.livejournal.com
В ghc недавно реализовали именованные образцы.

Плюс, часть этого есть во view patterns.

Date: 2014-04-17 11:29 am (UTC)
From: [identity profile] janatem.livejournal.com
Да, спасибо. Мне [livejournal.com profile] zelych уже указал на ViewPatterns/PatternGuards. Вроде бы в точности оно, только синтаксис несколько тяжеловесный.

Date: 2014-04-17 11:46 am (UTC)
From: [identity profile] thesz.livejournal.com
https://ghc.haskell.org/trac/ghc/wiki/PatternSynonyms

January 2026

S M T W T F S
    1 2 3
4 5 6 7 8 910
11 12 1314 15 1617
18192021222324
25262728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 18th, 2026 04:45 pm
Powered by Dreamwidth Studios