Эрланг (функциональное программирование) и объектно-ориентированное программирование с точки зрения мышления

Я изучаю Erlang, и я пытаюсь создать очень простую программу для блога. Однако мой ум в настоящее время попал в мир ОО (var p = new Post(); p.title=""; p.Save();). Я хотел бы понять некоторые основные мысли в Эрланге. Вместо создания объекта Post, что я должен делать с точки зрения структуры данных (p.Title, p.DateCreated, p.Body)? Должен ли я использовать кортеж? Я хотел бы понять рекомендуемый способ делать такие вещи (как для специфического, так и для функционального программирования Erlang). Или это то, что я делаю принципиально неправильно в Erlang или FP?

Требование (в терминах OO, не уверен, как объяснить в терминах FP еще ^ _ ^):

  • создать объект Post (id, title, date_created, body, IList)
  • создать объект Comment (id, post_id, created_by (имя как строка), date_created)
  • одно сообщение может иметь несколько комментариев
  • post.AddComment(комментарий)

Спасибо.

Обновлено: Я не ищу конкретного способа делать ООП в Эрланге, если это не рекомендуется. Я ищу стандартный/рекомендуемый способ делать то, что описано в вопросе, однако я не пытаюсь повторить ООП в Эрланге.

Ответы

Ответ 1

Я бы использовал записи:

-record(post, {title, date_created, body, comments = []}).
-record(comment, {created_by, date_created, content}).

Затем, если вы хотите использовать mnesia как базу данных:

Post = #post{title = "", body = "", date_created = erlang:universaltime()},
mnesia:transaction(fun() -> mnesia:write(Post) end).

Добавить комментарий:

Comment = #comment{created_by = "", content = "", date_created = erlang:universaltime()},
mnesia:transaction(fun() ->
    [Post] = mnesia:read(post, Title),
    PostWithNewComment = Post#post{comments = [Comment | Post#post.comments]},
    mnesia:write(PostWithNewComment)
end).

Я не тестировал код, но это то, что я бы сделал. Также я предположил, что каждое название уникально.

Ответ 2

Эрланг - это объектно-ориентированный язык. Это утверждение имеет больше возможностей, если вы посмотрите на ООП, как описал его Алан Кей:

OOP для меня означает только обмен сообщениями, локальный сохранения и защиты и процесс состояния и экстремальный поздняя привязка всех вещей.

Как вы, должно быть, знаете, Erlang продвигает стиль программирования под названием Concurrency Ориентированное программирование, в котором вы абстрагируете объекты как независимые процессы, которые обмениваются сообщениями. Каждый процесс имеет локальное состояние, они живут в своем параллельном мире. Динамический полиморфизм достигается тем, что вы можете определить класс процессов, которые могут отвечать на общий набор сообщений. Поскольку объекты Эрланга "живут" в своем крошечном процессе, он становится естественной средой для моделирования реального мира. Вы можете лучше использовать свои навыки ООП в Эрланге, чем на любом другом языке.

Невозможно дать полное описание ООП в Эрланге в таком маленьком пространстве. Я предлагаю вам прочитать книгу Программирование Erlang: Программное обеспечение для параллельного мира.

Также см. следующие ссылки:

Ответ 3

Ваш пример действительно не представляет собой хороший стиль OO. Комментарии появляются на уже опубликованных сообщениях в блогах, поэтому к тому времени у вас просто есть какая-то ссылка на сообщение, на которое отправляется комментарий.

Для программирования OO было бы разумнее иметь какой-то объект BlogDb, на который отправляются сообщения и объекты комментариев. Объект комментария должен знать, какой почтовый идентификатор является комментарием. Вы не должны создавать объекты post и comment с помощью "нового" оператора, вместо этого интерфейс BlogDb имеет методы, которые возвращают новые экземпляры этих файлов.

Внезапно у вас есть приемлемый способ реализовать то же самое в Erlang. Запустите gen_server, который является blog_db. Сделайте что-нибудь вроде

Post = myblog:post(Title, Body),
{ok, Result} = myblog:add_post(BlogDb, Post),
...

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

Ответ 4

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

Алан Кей - создатель Smalltalk вместе с Дэном Ингаллсом. Если вы посмотрите на Smalltalk, становится ясно, что он означает при обмене сообщениями: сообщение отправляется на какой-либо объект-получатель, например aBumblebee.fly(). Я разработал почти 10 лет с Smalltalk. Я немного знаю, как он разработан. Но то, что делается в Erlang, это fly (aBumblebee), где aBumblebee также не является экземпляром класса.

Я не уверен в этом, но когда вы смотрите на актеров в Эрланге, они также, похоже, не обмениваются сообщениями. Насколько я понимаю, Эрланг до сих пор получил конструкцию {case {...}}, потому что сообщения должны быть получены из некоторого списка. Нет другого способа отправить его получателю.

Если Эрланг был ОО, также не было бы необходимости в этих случаях в случае. Они необходимы, потому что нет позднего связывания. Да, есть динамический вызов в Эрланге. Но динамическая отправка сообщений и это то, что связано с поздним связыванием: указатель функции для перехода в нее не определяется во время компиляции, но просматривается во время выполнения. Поскольку все функции в Erlang являются глобальными, в любом случае нет необходимости искать какой-либо класс. Кроме того, я не вижу, каким образом защита существует в Эрланге. Как вы предоставляете инкапсуляцию, если нет класса, модуля или чего-то еще? Для записи все поля являются общедоступными.