Functional programming 从思维角度看Erlang(函数式编程)与面向对象编程

Functional programming 从思维角度看Erlang(函数式编程)与面向对象编程,functional-programming,erlang,oop,Functional Programming,Erlang,Oop,我正在学习Erlang,并试图创建一个非常简单的博客程序。然而,我的思维目前被困在OO世界中(var p=new Post();p.Title=“”;p.Save();)。我想了解一些关于二郎的基本想法。在数据结构(p.Title,p.DateCreated,p.Body)方面,我应该做什么来代替创建Post对象?我应该使用tuple吗?我想了解做这些事情的推荐方法(特定于Erlang和/或特定于函数式编程)。还是我在Erlang或FP中所做的根本错误 需求(用OO术语,不确定如何用FP术语解释

我正在学习Erlang,并试图创建一个非常简单的博客程序。然而,我的思维目前被困在OO世界中(var p=new Post();p.Title=“”;p.Save();)。我想了解一些关于二郎的基本想法。在数据结构(p.Title,p.DateCreated,p.Body)方面,我应该做什么来代替创建Post对象?我应该使用tuple吗?我想了解做这些事情的推荐方法(特定于Erlang和/或特定于函数式编程)。还是我在Erlang或FP中所做的根本错误

需求(用OO术语,不确定如何用FP术语解释):

  • 创建帖子对象(id、标题、创建日期、正文、IList)
  • 创建注释对象(id、发布id、创建人(名称为字符串)、创建日期)
  • 一篇文章可以有多条评论
  • post.AddComment(Comment)
  • 谢谢

    更新: 我不是在寻找在Erlang中执行OOP的具体方法,除非这是推荐的方法。我正在寻找标准/推荐的方法来完成问题中所描述的工作,但是我不想在Erlang中复制OOP。

    Erlang是一种面向对象的语言。如果你按照Alan Kay的描述来看待OOP,这句话会更有说服力:

    对我来说,OOP只意味着本地消息传递 保留、保护和隐藏 国家进程和极端 所有东西的后期装订

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

    在这么小的空间里,无法给出Erlang中OOP的完整描述。我建议你读这本书

    另请参见以下链接:

    • (采访)

      • 您的示例并不真正代表良好的OO风格。评论会出现在已经发布的博客帖子上,因此到那时,您只需要对该评论发布到的帖子id进行某种引用

        对于OO编程来说,使用某种BlogDb对象将post和comment对象发送给它更有意义。注释对象需要知道它是要注释的帖子id。您不应该使用“new”操作符创建post和comment对象,相反,BlogDb接口具有返回这些对象的新实例的方法

        突然间,您有了一种在Erlang中实现相同功能的可行方法。启动博客数据库的gen_服务器。做像这样的事情

        Post = myblog:post(Title, Body),
        {ok, Result} = myblog:add_post(BlogDb, Post),
        ...
        
        您不需要知道Post值的详细信息,因此它的构造方式隐藏在另一个模块中的“构造函数”中。

        我将使用记录:

        -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).
        
        我还没有测试代码,但这就是我要做的。我还假设每个标题都是唯一的

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

        艾伦·凯和丹·英格尔是Smalltalk的创始人。如果你看一下Smalltalk,就会明白他在消息传递中的意思:消息被发送到某个接收方对象,比如aBumblebee.fly()。我在Smalltalk工作了将近10年。我对它的设计略知一二。但在Erlang中所做的是fly(aBumblebee),其中aBumblebee也不是类的实例

        我不确定这一点,但当你观察Erlang中的演员时,他们似乎也不会交换信息。据我所知,Erlang到目前为止这种receive{case{…}}结构是因为必须从某个列表中检索消息。没有其他方法将其发送给收件人参与者


        如果Erlang是OO,那么在case语句中也不需要这些语句。它们是必需的,因为没有后期绑定。Erlang中有动态调用,是的。但是没有消息的动态调度,这就是后期绑定的意义:要跳转到的函数指针不是在编译时定义的,而是在运行时查找的。由于Erlang中的所有函数都是某种全局函数,因此无论如何都不需要从某个类进行查找。另外,我不知道Erlang中存在什么样的保护。如果没有类、模块或其他东西,如何提供封装?对于记录,所有字段都是公共的。

        可以使用元组代替对象,但使用记录可能更清晰。(在Erlang中记录会转换成元组。)@Nate谢谢你,因为我以前不知道这个关键字。这里有一个顶级谷歌搜索结果仅供参考@Nate私有状态和方法是如何使用记录表示的?你能解释一下如何有效地使用记录来代替类、接口等吗?@杰夫瑞:在OO术语中,你想把所有的对象都存储在内存中,用指针来表示,或者你认为把它们存储在某种类型的数据库中(也许使用ORM)?@ ZED,现在,为了学习目的,我不会接触数据库。方法、私有状态等呢?可以创建一个模块并导出这些函数:post:save(Title,Body)->ok{error,Reason}。post:save_comment(postitle,CommentBody,CreatedBy)->ok{error,Reason}我不知道你说的“私人”是什么意思state@TP问题是如何在Erlang中进行OOP。如何使用Erlang模拟具有状态和方法的对象,同时对对象的用户隐藏细节?(当然,Erlang中没有可变状态,但对象的用户不需要知道它是如何