Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby Erlang参与者与OOP对象有何不同?_Ruby_Oop_Functional Programming_Erlang - Fatal编程技术网

Ruby Erlang参与者与OOP对象有何不同?

Ruby Erlang参与者与OOP对象有何不同?,ruby,oop,functional-programming,erlang,Ruby,Oop,Functional Programming,Erlang,假设我有一个Erlang actor,定义如下: counter(Num) -> receive {From, increment} -> From ! {self(), new_value, Num + 1} counter(Num + 1); end. class Counter def initialize(num) @num = num end def increment @num += 1

假设我有一个Erlang actor,定义如下:

counter(Num) ->
  receive
    {From, increment} ->
      From ! {self(), new_value, Num + 1}
      counter(Num + 1);
  end.    
class Counter
  def initialize(num)
    @num = num
  end

  def increment
    @num += 1
  end
end
类似地,我有一个定义如下的Ruby类:

counter(Num) ->
  receive
    {From, increment} ->
      From ! {self(), new_value, Num + 1}
      counter(Num + 1);
  end.    
class Counter
  def initialize(num)
    @num = num
  end

  def increment
    @num += 1
  end
end
Erlang代码采用函数式编写,使用尾部递归来维护状态。然而,这种差异有什么有意义的影响?在我天真的眼中,这两件事的接口似乎大同小异:你发送一条消息,状态得到更新,然后你得到新状态的表示

函数式编程通常被描述为与OOP完全不同的范例。但Erlang actor似乎完全完成了对象应该做的事情:维护状态、封装和提供基于消息的接口

换句话说,当我在Erlang参与者之间传递消息时,它与在Ruby对象之间传递消息时有何不同

我怀疑函数/OOP二分法的后果比我所看到的更大。有人能指出吗

让我们暂且不提Erlang actor将由VM调度,因此可能与其他代码并发运行这一事实。我意识到这是Erlang和Ruby版本之间的主要区别,但这不是我要说的。在其他语言(包括Ruby)中,并发是可能的。虽然Erlang的并发性能可能会有很大的不同(有时会更好),但我并不是在问性能上的差异


相反,我更感兴趣的是功能与面向对象的问题。

IMHO这不是FP与面向对象的最佳示例。差异通常表现在访问/迭代和链接对象上的方法/函数上。此外,可能理解什么是“当前状态”在FP中更有效

在这里,您将两种截然不同的技术放在了一起。一个是F,另一个是OO

我能马上发现的第一个区别是内存隔离。消息在Erlang中序列化,因此更容易避免竞争条件

第二个是内存管理细节。在Erlang中,消息处理分为发送方和接收方。Erlang VM持有两组进程结构锁。因此,当发送方发送消息时,他获取的锁不会阻止主进程操作(由主锁访问)。总之,相对于Ruby端的完全随机行为,它使Erlang具有更软的实时性

换句话说,当我在Erlang参与者之间传递消息时,它与在Ruby对象之间传递消息时有何不同

不同之处在于,在Ruby等传统语言中,没有消息传递,只有在同一线程中执行的方法调用,如果您有多线程应用程序,这可能会导致同步问题。所有线程都可以访问彼此的线程内存


在Erlang中,所有参与者都是独立的,改变另一个参与者状态的唯一方法是发送消息。没有进程可以访问任何其他进程的内部状态。

从外部看,参与者类似于对象。它们封装状态并通过消息与世界其他地方通信以操纵该状态

要了解FP是如何工作的,您必须查看参与者的内部并了解它是如何改变状态的。您的状态为整数的示例太简单了。我没有时间提供完整的示例,但我将草拟代码。通常,参与者循环如下所示:

loop(State) ->
  Message = receive
  ...
  end,
  NewState = f(State, Message),
  loop(NewState).
与OOP最重要的区别在于没有变量突变,即NewState是从状态获得的,可能与状态共享大部分数据,但状态变量始终保持不变

这是一个很好的属性,因为我们从不破坏当前状态。函数f通常会执行一系列转换,将状态转换为NewState。只有当它完全成功时,我们才能通过调用loop(NewState)将旧状态替换为新状态。 因此,重要的好处是我们国家的一致性

我发现的第二个好处是代码更简洁,但要适应它需要一些时间。通常,由于不能修改变量,所以必须将代码划分为许多非常小的函数。这实际上很好,因为您的代码将得到很好的分解

最后,由于无法修改变量,因此更容易对代码进行推理。对于可变对象,您永远无法确定是否会修改对象的某些部分,如果使用全局变量,情况会越来越糟。在执行FP时不应遇到此类问题


要进行尝试,您应该尝试使用纯erlang结构(而不是actors、ets、mnesia或proc-dict)以函数方式操作一些更复杂的数据。或者,您可以在ruby中尝试使用Erlang,它包括Alan Kay的OOP(Smalltalk)的消息传递方法和Lisp中的函数式编程

您在示例中描述的是面向对象的消息方法。Erlang进程发送消息的概念类似于Alan Kay的对象发送消息。顺便说一句,您可以检索这个概念,这个概念也在并行运行的对象之间发送消息的地方实现

函数式编程就是如何对过程进行编码。例如,不能修改Erlang中的变量。设置好后,您只能读取它们。您还有一个列表数据结构,它与Lisp列表非常相似,并且由Lisp的lambda提供

在Erlang中,消息在一侧传递,函数在另一侧传递是两个完全不同的东西。在编写现实生活中的erlang应用程序时,98%的时间用于功能编程,2%的时间用于消息传递,这主要用于可伸缩性和并发性。换句话说,当您遇到棘手的复杂编程问题时,您可能会使用Erlang的FP端来实现算法的细节,并使用消息传递来实现可伸缩性
ThingPid ! {self(),fun(X,X) -> 0; (X,_) -> X end,10}.
% which will do nothing, unless the internal value = 10 and in this case will go directly to 0 and exit