用actor替换class关键字会导致错误

用actor替换class关键字会导致错误,class,actor,ponylang,Class,Actor,Ponylang,这是我的密码: class Eapproximator var step : F64 new create(step' :F64) => step = step' fun evaluate() :F64 => var total = F64(0) var value = F64(1) while total < 1 do total = total + step value = value + (value

这是我的密码:

class Eapproximator
  var step : F64
  new create(step' :F64) =>
    step = step'

  fun evaluate() :F64 =>
    var total = F64(0)
    var value = F64(1)
    while total < 1 do
      total = total + step
      value = value + (value * step)
    end
    value

actor Main
  new create(env: Env) =>
    var e_approx = Eapproximator(0.00001)
    var e_val = e_approx.evaluate()
    env.out.print(e_val.string())

我能做些什么来解决这个问题?

参与者是小马中的并发单元。这意味着同一程序中的许多不同参与者可以同时运行,包括
Main
Eapproximator
参与者。现在,如果一个参与者的字段同时被多个参与者修改,会发生什么?由于并发程序在现代硬件上的工作方式,您最终很可能会得到一些垃圾值。这就是所谓的数据竞赛,它是并发编程中许多错误的根源。Pony的目标之一是在编译时检测数据竞争,而此错误消息是编译器告诉您您尝试执行的操作可能不安全

让我们浏览一下错误消息

接收器类型不是目标类型的子类型

接收器类型是被调用对象的类型,
e_约
。目标类型是方法内部的
this
类型,
Eapproximator.evaluate
。子类型化意味着子类型的对象可以像父类型的对象一样使用。因此,该部分告诉您,由于类型不匹配,
evaluate
无法在
e_approx
上调用

接收器类型:Eapproximator标签

e_近似值
是一个
Eapproximator标签
标记
对象既不能读取也不能写入。我将在一分钟内详细说明为什么
e_approx
tag

目标类型:EAP Proximator box

内部的
评估
是一个
Eapproximator框
对象可以读取,但不能写入
这是
,因为
评估
被声明为
fun evaluate
,这意味着
fun box evaluate
(这意味着默认情况下,方法无法修改其接收者。)

Eapproximator标记不是Eapproxim的子类型 ator box:标记不是box的子映射

根据此错误消息,
标记
对象不是
对象的子类型,这意味着
标记
不能像使用
框一样使用。如果我们看一下
标签
允许什么,这是合乎逻辑的<代码>框
允许的内容多于
标记
:它可以读取,而
标记
不能读取。一个类型只能是另一个类型的子类型,如果它允许的内容少于(或等于)超类型

那么,为什么用
actor
替换
class
会使对象
标记
?这与我前面提到的数据竞争问题有关。演员可以自由支配自己的领域。它可以读和写给他们。由于参与者可以并发运行,因此必须拒绝他们访问彼此的字段,以避免与字段所有者的数据竞争。而在类型系统中有一些东西正是这样做的:
tag
。参与者只能将其他参与者视为
标记
,因为读取或写入它们是不安全的。对于那些
标记
引用,它可以做的主要有用的事情是发送异步消息(通过调用
be
方法或行为),因为这既不是读也不是写

当然,由于您的程序中没有对
Eapproximator
进行任何变异,因此您的特定病例是安全的。但是,试图禁止每一个不安全的程序要比试图允许除此之外的每一个安全程序容易得多

总而言之,除了将
Eapproximator
作为一个类保留外,您的程序实际上没有任何修复方法。在小马节目中当演员不需要任何东西。参与者是并发性的单位,但这意味着它也是顺序性的单位。需要连续和同步的计算必须在单个参与者中进行。然后,您可以将这些计算分解为不同的类,以保持良好的代码卫生

Error:
/src/main/main.pony:18:34: receiver type is not a subtype of target type
    var e_val = e_approx.evaluate()
                                 ^
    Info:
    /src/main/main.pony:18:17: receiver type: Eapproximator tag
        var e_val = e_approx.evaluate()
                    ^

    /src/main/main.pony:6:3: target type: Eapproximator box
      fun evaluate() :F64 =>
      ^
    /src/main/main.pony:3:3: Eapproximator tag is not a subtype of Eapproxim
ator box: tag is not a subcap of box
      new create(step' :F64) =>
      ^
Error:
/src/main/main.pony:19:19: cannot infer type of e_val

    env.out.print(e_val.string())