Erlang(函数式编程)与面向对象编程在思维上的比较

发布于 2024-08-12 19:34:23 字数 619 浏览 1 评论 0原文

我正在学习 Erlang,我正在尝试创建一个非常示例的博客程序。然而,我的思想目前陷入了面向对象的世界var p = new Post(); p.Title = ""; p.Save();)。我想了解Erlang的一些基本思想。我应该在数据结构(p.Title、p.DateCreated、p.Body)方面做什么,而不是创建 Post 对象?我应该使用元组吗?我想了解做这些事情的推荐方法(在 Erlang 特定和/或函数式编程特定中)。或者我在 Erlang 或 FP 中所做的事情根本就是错误的?

需求(用OO术语来说,还不知道如何用FP术语解释^_^):

  1. 创建Post对象(id,title,date_created,body,IList)
  2. 创建Comment对象(id,post_id,created_by(名称为字符串),date_created )
  3. 一个帖子可以有多个评论
  4. 帖子。AddComment(评论)

谢谢。

更新: 我并不是在寻找在 Erlang 中进行 OOP 的特定方法,除非它是推荐的方法。我正在寻找执行问题中描述的标准/推荐方法,但是我并不想在 Erlang 中复制 OOP。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

遇见了你 2024-08-19 19:34:23

Erlang是一种面向对象的语言。如果您按照 Alan Kay 的描述来看待 OOP,则该语句更有力量:

OOP 对我来说意味着仅消息传递、本地
保留、保护和隐藏
状态过程和极端
所有事物的后期绑定。

您必须知道,Erlang 提倡一种称为“面向并发编程”的编程风格,在这种风格中,您将对象抽象为通过消息传递进行通信的独立进程。每个进程都有它的本地状态,它们生活在自己的平行世界中。动态多态性是通过以下事实实现的:您可以定义可以响应一组通用消息的进程。由于 Erlang“对象”生活在它们自己的微小过程中,因此它成为对现实世界进行建模的自然媒介。与任何其他语言相比,您可以在 Erlang 中更好地利用您的 OOP 技能。

在这么小的篇幅里无法完整描述 Erlang 中的 OOP。我建议你阅读Programming Erlang: Software for a Concurrent World这本书。

另请参阅以下链接:

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:

梦过后 2024-08-19 19:34:23

我会使用记录:

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

我还没有测试代码,但这就是我要做的。我还假设每个标题都是唯一的。

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.

莫多说 2024-08-19 19:34:23

你的例子并不能真正代表良好的面向对象风格。评论出现在已经发布的博客文章上,因此到那时您就拥有了对评论发布到的帖子 ID 的某种引用。

对于面向对象编程来说,拥有某种可以向其发送帖子和评论对象的 BlogDb 对象会更有意义。评论对象需要知道它所评论的帖子 ID。您不应该使用“new”运算符创建帖子和评论对象,而是 BlogDb 接口具有返回这些对象的新实例的方法。

突然之间,你就有了一种在 Erlang 中实现同样功能的可行方法。启动 gen_server,即 blog_db。做类似的事情

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

您不需要知道 Post 值的详细信息,因此它的构造方式隐藏在另一个模块中的“构造函数”中。

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.

ㄟ。诗瑗 2024-08-19 19:34:23

OOP 对我来说仅意味着消息传递、本地保留和保护以及状态进程的隐藏,
以及所有事物的极端后期绑定。

Alan Kay 与 Dan Ingalls 共同创建了 Smalltalk。如果您查看 Smalltalk,就会清楚他对消息传递的含义:消息被发送到某个接收者对象,例如 aBumblebee.fly()。我已经使用 Smalltalk 开发了近 10 年。我知道它是如何设计的。但 Erlang 中所做的是 Fly(aBumblebee),其中 aBumblebee 也不是类的实例。

我对此不确定,但是当你查看 Erlang 中的 Actor 时,他们似乎也没有交换消息。据我了解 Erlang 到目前为止,这种 receive { case { ... } } 构造是因为必须从某个列表中检索消息。没有其他方法可以将其发送给接收演员。

如果 Erlang 是面向对象的,那么也就不需要这些 when-case 语句。它们是必要的,因为没有后期绑定。 Erlang 中有动态调用,是的。但是没有消息的动态分派,这就是后期绑定的意义:要跳转到的函数指针不是在编译时定义的,而是在运行时查找的。由于 Erlang 中的所有函数都是全局的,因此无论如何都不需要从某个类进行查找。另外,我不明白 Erlang 中以何种方式存在保护。如果没有类、模块什么的,你如何提供封装?作为记录,所有字段都是公开的。

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

Alan Kay is the creator of Smalltalk together with Dan Ingalls. If you look at Smalltalk it becomes clear what he means with messaging: a message is sent to some receiver object like aBumblebee.fly(). I've developed almost 10 years with Smalltalk. I know a bit how it is designed. But what is done in Erlang is fly(aBumblebee) where aBumblebee is also not an instance of a class.

I'm not sure about this, but when you look at actors in Erlang they also don't seem to exchange messages. As I understand Erlang so far this receive { case { ... } } construction is because the messages have to be retrieved from some list. There is no other way to send it to the recipient actor.

If Erlang were OO there would also be no need for these when-case statements. They are necessesary, because there is no late binding. There is dynamic invocation in Erlang, yes. But no dynamic dispatch of messages and that is what late binding is about: the function pointer to jump to is not defined at compile time but looked up at runtime. Since all functions in Erlang are kind of global, there is no lookup from some class needed anyway. Also, I don't see in what way protection exists in Erlang. How do you provide encapsulation if there is no class, module or something? For a record all fields are public.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文