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

问题描述 投票:3回答:1

这是我的代码:

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

它运作良好并打印(如预期)2.7183。但是,如果我在class定义中用actor替换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())

我该怎么做才能解决这个问题?

class actor ponylang
1个回答
4
投票

actor是Pony中的并发单元。这意味着同一个程序中的许多不同演员可以同时运行,包括你的MainEapproximator演员。现在如果一个演员的领域被多个演员同时修改会发生什么?由于并行程序在现代硬件上的工作方式,你最有可能最终得到一些垃圾值。这称为数据竞争,它是并发编程中许多错误的来源。 Pony的目标之一是在编译时检测数据竞争,并且此错误消息是编译器告诉您正在尝试执行的操作可能不安全。

让我们来看看那个错误信息。

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

接收器类型是被调用对象的类型,e_approx在这里。目标类型是方法内部的this类型,Eapproximator.evaluate在这里。子类型意味着可以使用子类型的对象,就好像它是超类型的对象一样。所以这部分告诉你,由于类型不匹配,evaluate无法在e_approx上调用。

接收器类型:Eapproximator标签

e_approx是一个Eapproximator tagtag对象既不能读也不能写。我将在一分钟内详述为什么e_approxtag

目标类型:Eapproximator框

this里面的evaluate是一个Eapproximator box。可以读取box对象,但不能写入。 thisbox,因为evaluate被声明为fun evaluate,隐含地意味着fun box evaluate(这意味着默认情况下,方法不能修改他们的接收器。)

Eapproximator标签不是Eapproxim ator框的子类型:标签不是框的子标签

根据此错误消息,tag对象不是box对象的子类型,这意味着tag不能被用作box。如果我们看一下tagbox允许的内容,这是合乎逻辑的。 box允许更多的东西比tag:它可以阅读,而tag不能。如果类型允许的内容少于(或同样多)超类型,则类型只能是另一种类型的子类型。

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

当然,既然你没有对你的程序进行Eapproximatorin的任何变异,你的具体情况就是安全的。但是,尝试禁止每个不安全的程序要比尝试允许除此之外的每个安全程序容易得多。

总而言之,除了将Eapproximator保持为一个类之外,您的程序并没有真正的修复。没有任何东西需要成为Pony计划中的演员。 actor是并发的单位,但这意味着它也是顺序的单位。需要顺序和同步的计算必须存在于单个actor中。然后,您可以将这些计算细分为各种类,以实现良好的代码卫生。

© www.soinside.com 2019 - 2024. All rights reserved.