views:

605

answers:

3

I am learning Erlang and I am trying to create a very sample blog program. However my mind currently is trapped in the OO world (var p = new Post(); p.Title = ""; p.Save();). I would like to understand some basic thinkings in Erlang. Instead of creating Post object what I should do in terms of data structure (p.Title, p.DateCreated, p.Body)? Should I be using tuple? I would like to understand the recommended way in doing such things (in both Erlang specific and or Functional Programming specific). Or is what I am doing fundamentally wrong in either Erlang or FP?

Requirement (in OO terms, not sure how to explain in FP terms yet ^_^):

  1. create Post object (id, title, date_created, body, IList)
  2. create Comment object (id, post_id, created_by (name as string), date_created)
  3. one Post can have multiple comments
  4. post.AddComment(Comment)

Thanks.

Updated: I am not looking for specific way of doing OOP in Erlang unless it's the recommended way. I am looking for standard/recommended way of doing what's described in the question, however I am not trying to replicate OOP in Erlang.

+4  A: 

Erlang is an Object Oriented language. This statement has more power if you look at OOP the way Alan Kay described it:

OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things.

As you must be aware, Erlang promotes a style of programming called Concurrency Oriented Programming, in which you abstract away objects as independent processes that communicate by message passing. Each process has it's local state, they live in their own parallel world. Dynamic polymorphism is achieved by the fact that, you can define a class of processes that can respond to a common set of messages. As Erlang 'objects' live in their own tiny process, it becomes a natural medium for modelling the real-world. You can make use of your OOP skills better in Erlang than in any other language.

Can't give a full description about OOP in Erlang in such a small space. I suggest that you read the book Programming Erlang: Software for a Concurrent World.

Also see these links:

Vijay Mathew
I thought Joe Armstrong never admitted Erlang is an OO language.
Jeffrey C
@Jeffrey I don't know if Joe Armstrong admits Erlang as OO or not, but if you go by the strictest definition of OOP, Erlang is one of the rare languages that lets you program in that paradigm.
Vijay Mathew
Joe admits it in the strictest Alan Kay sense, but definitely not in the more common classes/objects/hierarchies sense, i.e. what is commonly meant by the term OOP. Accept there is a cross here to ward off the OOP evils! :-)
rvirding
I agree with Joe.
rvirding
A: 

Your example doesn't really represent good OO style. Comments appear on already published blog posts, so by then you just have some kind of reference to the post id the comment is posted to.

For OO programming it would make more sense to have some kind of BlogDb object that one send post and comment objects to. A comment object needs to know what post id it is a comment to. You should not create post and comment objects using the 'new' operator, instead the BlogDb interface has methods that return fresh instances of those.

Suddenly you have a passable way to implement just the same thing in Erlang. Start a gen_server that is the blog_db. Do things like

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

You don't need to know the details of the Post value, so how it is constructed is hidden in a "constructor" for it in another module.

Christian
Why would people always comment on how bad the examples are in the question? It's meant to be example, for a quick reference only, to help whoever understands the question better, not some sort of "well designed, patterned example"!
Jeffrey C
Because well designed OO is quite similar to "CO".
Christian
+5  A: 

I would use records:

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

Then if you want to use mnesia as database:

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

To add a comment:

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).

I haven't tested the code, but this is what I would do. Also I assumed that each title is unique.

TP
What about methods, private state etc?
Vijay Mathew
maybe create a module and export these functions:post:save(Title, Body) -> ok | {error, Reason}.post:save_comment(PostTitle, CommentBody, CreatedBy) -> ok | {error, Reason} ?I am not sure what you mean by private state
TP
@TP The question is about doing OOP in Erlang. How can Erlang be used to simulate objects with state and methods, while hiding the details from the user of the object? (Of course, there is no mutable state in Erlang, but the user of the object need not be aware of how it is handled internally) I think processes are better than records in simulating real objects.
Vijay Mathew
@TP Personally, I have no problem with your method. But it is similar to how we use structs in C and do not simulate objects that can respond to messages.
Vijay Mathew
I wouldn't consider doing OOP in Erlang since it is intended to be a functional programming language. To hide the details from the user you may want to create a new method and return an object, have a look at ets:new/2 (http://www.erlang.org/doc/man/ets.html#new-2). If you really want to do OOP, you should read this question: http://stackoverflow.com/questions/1063497/hidden-features-of-erlang (inheritance and parameterized modules)
TP
@Vijay, perhaps you misunderstood my question, I am not looking at doing OOP in Erlang. What I meant was my understanding is restricted to how OOP works and I want to know how to do similar things in Erlang, not strictly the OOP way.
Jeffrey C