Pull to refresh

Comments 64

Про сопоставление как всегда кратко :( Хотя самое интересное же…

Можно ли написать шаблон условие что все входящие значения разные, т.е. например есть для триплетов вида {1,2,3} или {atom1, atom2, atom3} выпонялось, а для триплетов вида {1,1,1} или {atom1, atom2, atom1} нет?

Можно ли написать шаблон чтобы он проверял типы? Т.е. например требовал чтобы значение было всегда атомом, а второй переменной типа integer?

1. Почему нет? Что вас смущает?

2. Для этого есть guards. Я думаю, о них автор дальше напишет.
По превому все смущает, пример можно? Т.е. понятно как это сделать например для трех элементов

all_three_elements_of_list_is_different([_,R,R]) -> false;
all_three_elements_of_list_is_different([R,_,R]) -> false;
all_three_elements_of_list_is_different([R,R,_]) -> false;
all_three_elements_of_list_is_different([_,_,_]) -> true.

Но для четыре, пяти, шести и больше очень громоздко :)

По второму пункту — как же -spec для функций? Как раз же получается, что мы можем проверить тип значения? На этапе компиляции правда…

Ну и опять же у меня есть ощущение, что match specification мне поможет и в первом и во втором случае? Нет?
spec — это для dialyzer, это отдельный статический анализатор, к компилятору имеет весьма опосредованное отношение.
Это понятно, слово «компиляции» в кавычки взять нужно было. Но вопрос открытый — так одно даст проверить, что не тот тип передается или нет. Или с какой-то вероятностью?
А черт его знает. Типы, говорят, годно проверяет, пока все покрыто спеками.

>> все входящие значения разные
Не сможет.
2. Как вам поможет spec для сопосотавления с образцом? Вы же хотите разные реализации функции в зависимости от типа аргумаента, правильно я понимаю? С помощью spec же можно проверить, можно такую функцию с такими типа аргументов вызывать в принципе.

И каким образом вы хотите задействовать тут match specification?
И все же возвращаясь к пункту 1 — как сделать так чтобы матчилось если все элементы списка (или просто все параметры) разные?

По второму, я спросил — match specification поможет или нет?
Я полагаю, что в общем случае так же, как и в любом другом языке. Сравнением. Сравнение с образцом по сути так же выполняется же — берется первый вариат, проверятся, если не подходит — берется второй вариант и т.д.

Я не вижу, как вообще match specification сюда прикрутить, но вы его приводите — может, вы чего-то знаете, что я пропустил?
Ну вот смотрите как я рассуждаю, мы можем сделать так

1> Tmp = ets:new(table, []). 16400 2> ets:insert(Tmp, {1,2,3}). true 3> ets:insert(Tmp, {1,2,1}).

А потом как нибудь так

ets:match(Tmp, [{'$1','$2','$3'}, {'>','$3', 2}]).

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

И я например логично ожидаю что можно было бы описать функцию примерно таким образом

fun([{'$1','$2','$3'}, {'>','$3', 2}]) ->

Которая работала бы аналогично — т.е. ожидала триплеты, и матчилась только для триплетов у которых третий элемент больше 2

Т.е. с одной стороны мы можем по патерну выбирать данные с условиями которые добавлены через ets:insert — с другой не можем так же по такому же паттерну матчить их как входящие параметры функции, а вынуждены делать это через гуарды
Всегда считал что «переменные, которые нельзя изменять» называются — именованные константы.
Математика не согласна.
На самом деле там не совсем переменные и не совсем константы. Их нельзя изменить, но им можно сколько угодно раз присвоить (одно и то же) значение.

Грубо говоря, когда вы вводите новый идентификатор, он не связан ни с каким значением. Операция присваивания или вызов функции производят сопоставление с образцом, связывая при этом несвязанные ранее имена. В дальнейшем, после связывания, присваивание будет просто сопоставлять с образцом.
В англоязычной литературе это обычно называется binding — привязка имени к значению/выражению.
Имхо, лучше что-нибудь на примерах в дальнейшем. Но вообще, это все равно очень полезно! Спасибо.
Примеры обязательно будут. Здесь я тоже старался показывать на примерах (тот же генератор списков), но в данной статье все примеры слишком элементарные.

Дальше будет интересней, я обещаю.
Почему нельзя сопоставлять уже связанные переменные?
Вполне же рабочий код
1> A = 5.
5
2> {A, _} = {5, whatever}.
{5, whatever}


А вот это так вообще бывает очень полезно
> F = fun([H | _], H) -> ok end. 
Неплохо было бы описать в чем минусы использования "++" и "--" в списках и в каких случаях их использование оправдано, а в каких — нет.

Извините конечно, но мне кажется что статей по типу введения в ерланг уже просто тонны. Все понятно и разжевано.

На мой взгляд неплохо было бы увидеть что-нибудь о менее описанных на русском темах типа:
«Как работает GC»
«Дебаггинг и профилирование в ерланге»
«Тонкости отстройки виртуальной машины» и прочее. Плохо освещена тема использования snmp фреймворка.
Возможно, вы не обратили внимание, но во вступлении я писал про это.
Проблема в том, что в на русском языке кроме таких элементарных вещей большие ничего не описывается. Я планирую описать все, но без основ, знания будут неполными. Потерпите немножко, дальше будут более сложные темы.
отлично, заранее спасибо!
Возможно стоит упомянуть, что для конкатенации строк используется оператор ++ или string:concat(A, B), а также про такой момент:

> A = "A" .
> B = "B" .
> C = 'C' .
>
> A ++ B .
AB 
>
> A ++ B ++ C.
[65,66|'C']
Про строки будет в другой статье.
Статья отличная, но про стоки совсем ничего нет. Буду ждать с нетерпением следующие статьи. Желаю автору не останавливаться на достигнутом и перевести весь learyousomeerlangforgreatgoods. Надеюсь когда-нибудь прочитать про FSM в эрланге на русском. И don't drink too much Kool-aid.
Вот эту штуку хабраэффектнуть тоже не помешает.
Автор, Erlang это хорошо, но делайте статьи длиннее. Те кому не интересно и так читать не будут, а кто таки захочет прочитать, может осилить и больший объем.
Вы несомненно правы, кому надо — осилят. Но глава должна быть логически целой.
Плюс к этому у меня самого уходит много времени на написание статей. К примеру на эту я потратил почти неделю (по вечерам после работы). Я не умею выражать свои мысли красиво, поэтому приходится подолгу подбирать слова. Если делать главы еще больше, то писать я их буду очень долго.
Ничего, к концу книги научитесь :)
Опишите в статье что такое операция «rem». Мне понять что такое «rem» практически невозможно.

7 rem 3.
1

Что сие значит? Остаток от деления с каким-то хитрым округлением вниз?

Далее она используется вроде как для определения четности, но так же не описана математика, остается только догадываться.
UFO just landed and posted this here
Вы не поверите, но есть люди для которых эрланг может оказаться первым языком. Я лично знаю пару прграммистов, которые начинали с функциональщины. Тяжело им, конечно, потом пришлось. Все таки для фукциональщиков работы в разы меньше, но ничего — работают.
И что бы они делали, если бы все учебные пособия были написаны так, как вы говорите?

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

Хотелось бы шаг за шагом какую-нибудь крутую штуку сделать :)
Спасибо за совет.
Я постараюсь придумать что-нибудь интересное и практически полезное.
Вот это точно. Реальных для бизнеса/энтерпрайза пару задачек, чтобы мы, сирые, могли увидеть выгоды/преимущества и функциональных языков в целом, и Эрланга в частности.
Вы смеетесь или серьезно?
Я все понимаю, примеры необходимы. Но как вы себе представляете пошаговое объяснение языка на примере сложной задачи с непростой логикой? Для решения такой задачи надо, как минимум, составить план. А как составить план, если на данный момент мы будем знать только самые основы?

Чесно говоря мне уже давно надоели вопросы типа «чем функциональные языки лучше императивных»? Да ничем. Они прсто-напрсто другие. Это как сравнивать синий и зеленый. Любую задачу можно решить на любом языке: где то оптимальнее на императивном, где то на функциональном. Мне ФЯ ближе по образу мышления, вот и нравятся. Но исторически так сложилось, что императивные языки более популярны. Из-за этого подавляющее число алгоритмов описаны в императивном стиле.

И человек, который много лет пишет на императивных языках начинает думать на них. И ФЯ кажутся ему неудобными и абсурдными потому, что он смотрит на них через призму императивщины.

Я, к примеру, считаю синтаксис ФЯ более читабельным. А Haskell вооще воплощением лаконичности. А из императивных языков мне только плюсы нравятся. Честное слово, надоели холивары на эту тему.

Извините меня, пожалуйста, если я вас неправильно понял и это был не сарказм. Накипело.
Никакого сарказма. Мой любимый язык — старый добрый Visual Basic. Процедурщина и объектно-ориентированность. Уже достаточно много лет успешно решаю задачи корпоративного класса. Я понимаю, что каждый инструмент хорош в своей области, вот и заинтересовало, можно ли что-то «условно-реально» полезное для корпоративной среды более элегантно, производительно или с меньшими трудозатратами закодить на Эрланге. Я не прошу разработать и реализовать многоуровневую сложную систему корпоративного класса ) Было бы интересно увидеть красивое решение хотя бы какой-то относительно простой подзадачи. Да хотя бы сортировки, или обработки текста, или матчинга строк, если Эрланг имеет в этой области какие-то сильные стороны… А ещё лучше — небольшой пример из жизни, как этот язык помог решить конкретную проблему.
В одной из ближайших статей, где будет разбираться хвостовая рекурсия, будет классический пример быстрой сортировки в лдну строку.
В принципе, Эрланг хорош при работе в качестве фронтенда для сетевого приложения. К примеру, принимает подключение, делает какие-нибудь несложные вычисления и передает поток выполнения дальше. Он нужен там, где надо решать очень большое колличество задач параллельно.

В первых статьях сложных примеров не будет по указанным выше причинам. А после изучения основ, скорее всего сделаю как вы просили. Поставим задачу и будем решать ее параллелно изучению.

P.s. На сколько я знаю, Erlang — не лучший выбор для работы со строками.
Вот и отлично. Спасибо! Ваша статья, кстати, гораздо понятнее книжки по Erlang, которую я не так давно прикупил.
Естественно, никто и не говорит, что нужно в первой же статье с места в карьер разбирать сложные темы. Речь-то шла о пожеланиях на будущее.
как можно вообще програмировать без изменяемых переменных?
Допустим у меня есть некий обьект и он имеет координы x, y и он может перемещятся.
Как мне такое написать на erlang?
присваивать новые x1, y1? тогда у меня будут уже совсем другие переменные с другим названием.
а как тогда мне например сравнить вновь полученные координы и любого другого обьекта? как вообше написать сравнение с переменной имя которой не знаешь заранее? (напр. x265)
Объект — процесс в виде ген_сервера, который хранит в себе стейт с координатами. Очевидно, что вы можете изменять стейт через посылку сообщений, либо получать этот стейт через синхронную посылку сообщений же.
Вы просто попробуйте попрограммировать на ерланге, для этого правда надо слегка повернуть мозг.
Похоже для вас это очевидно легко, а рабочий пример можете скинуть?
Правда не могу пробывать програмировать без примеров.
А пожалуйста :)

gist.github.com/2garryn/6745209

garry@debian:/tmp$ erl
Erlang R15B03 (erts-5.9.3.1) [source] [64-bit] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.9.3.1 (abort with ^G)
1> c(example).
{ok,example}
2> {ok, Pid} = example:start_link().
{ok,}
3> example:get_coordinates(Pid).
{0,0}
4> example:set_coordinates(Pid, {3,4}).
ok
5> example:get_coordinates(Pid).
{3,4}
10>
Не хочу показаться навязчивым, но реально поверачиваю мозг в другую сторону, пытаюсь понять как работает ваш пример.
Мы используем всего 2 метода.
example:set_coordinates
example:get_coordinates

Pid, я так понял, фактически локализирована внутри функций.
cast и call задаются через хендлер.

set_coors и get_coors — они откуда взялись…
и зачем нам handle_info, terminate, code_change и init?

Сумбур. Пока прочитать код не получается. Буду благодарен за помощь!

Чтобы понять нужно изучить как работает gen_server. Рекомендую прочитать в книге от Джо Армстронга — pragprog.com/book/jaerlang/programming-erlang Там есть глава про основные бехейвиоры OTP.
В кратце — Функция exampe:start_link/0 c помощью ген_сервера запускает отдельный процесс, пид которого возвращает.
Это процесс имеет свой собственный стейт. внутри которого хранятся значения X и Y. Стейт — последний аргумент в хендлерах ген_сервера — handle_call, handle_cast, handle_info.

Присмотритесь к колбеку:
handle_call(get_coors, _From, Position) ->
    {reply, Position, Position}.


В Position хранятся текущие координаты.

Это колбек будет вызван когда вы вызовете функцию
get_coordinates(Pid) ->
    gen_server:call(Pid, get_coors).


функции init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3 — их объявления требует behaviour, который вы реализуете. Это примерно как интерфейс в джаве.
Сорри за сумбурное объяснение. Я уверен, что вам будет все понятно, когда вы разберетесь с gen_server
Спасибо!
Я уже осилил вторую статью автора и вроде как (с натяжкой) начал понимать что происходит (:
Книжку обязательно почитаю!
Полностью согласен.
Все дело в том, что поставленую задачу вы пытаетесь решить методами императивных языков. ФЯ — это не только другие инструменты, но и другой подход, совершенно другой ход мыслей. И бывает сложно их осмыслить после большой практики императивного программирования.
тут был слизливый пост о том что как бы голову я не ломал, ход мыслей не менял — рабочего примера не появится…
Лично у меня на данный момент нет сколько-нибудь сложного кода т.к. на функциональных языках писать начал сравнительно недавно. Да и работы в моем городе на них не найдешь.

Я сделал у себя пометку на эту тему. Обещаю, что как только начну работать над реальным проектом с использованием ФЯ, я вам напишу и все покажу.
val object = new MovingObject(x: 10, y: -5);
val movedObject = object.copyWithPosition(x: 0, y: 0);

В чем Ваша проблема?
Спасибо, про ерланг на русском толкового мало, пишите еще.
(боюсь я ещё долго в плюс по карме не выползу но всёже)
«Я очень люблю функциональное программирование, и один из моих любимых языков — Erlang. »
Вы любите язык который не знаете?
Простите я правда думал что графу «от автора» написыли именно вы…
Ладно не суть. Это ваще лично дело что любить а что не любить.
Я опять придераюсь к мелочам. но вы говарите что с появлением работы у вас что-то измениться и вы сможете мне такое показать. Ежели это сейчас нельзя узнать без работы «где-то там» это…
*шопотом* это прям как комерческая тайна какаято…
А вы её раскроете, ай-яй-яй… как не хорошо получиться…

Эх если бы всё было так просто… Я бы уже давно сам програмировал на таком языке… Всё упирается в документацию, дальше которой всё — «весь придуманый код» никто не покажет(рабочий код)… Вы не задумывались почему?

всё просто его нетУ!
Если вам хочется почитать код на э-ге — смотрите в erlyvideo/flussonic, rabbitmq, riak, couchdb, ejabberd(не уверен, про него разное говорят). Это все готовые продукты, которые работают и, что немаловажно, приносят своим создателям деньги.
UFO just landed and posted this here
Это довольно сложные проекты. С OTP начинать ковыряться лучше с документации. И никогда не брать в пример код OTP. Порой он просто адовый
большое спасибо за статью, не взирайте на отзывы типа «зачем эта тягомотина»!
вопросы по теме:
1. непонятно какое применение у атомов, зачем они? чем атом отличается от строковой переменной?
2. чем отличаются «равно»(==) и «соответсвенно равно»(=:=)?
3. в чем разница по сути кортежа и списка в Эрланге, кроме того что список имеет голову и хвост? почему кортеж не аналог массива (array)?
1. Атом занимает в памяти одно слово. Используются много где. Как имена функций, рекордов, имена модулей итп
2. По сути «Равно» сравнивает два значения, тогда как «соответственно равно» сравнивает еще и типы.
Пример:

1> 3.0 == 3.
true
2> 3.0 =:= 3.
false

3. Кортеж — неизменяемый набор данных фиксированной длины. А array — это такая стильная модная реализация массивов.
Разница между кортежами и списками Как ее понял я.

Кортеж создается один раз и потом не может измениться, ни длинна ни содержимое.
Создается вручную.

Список имеет голову и хвост может изменяться как длинна так содержимое.
Интересно как поменять значение определенного елемента списка на другой?
Создается вручную или с помощью генератора.

Прошу подтверждения правильности у автора и у 2garryn
Представьте просто, что кортеж (тапл) это массив. Содержимое можно менять функцией setelement/3. Длину менять нельзя.

Список — это просто односвязный список. На голову и хвост его можно поделить операцией "|"
Меняется нужный элемент через lists:nth/3
А вообще стоит почитать литературку)

Sign up to leave a comment.

Articles