Chapel 中是否有与 Fortran 的 select 类型语句等效的语句?

Is there an equivalent to Fortran's select type statement in Chapel?

我想在 Chapel 中尝试 类 和多态性,所以我正在尝试 让以下示例代码起作用:

module SomeAnimals {

  class Animal {
  }

  class Bird: Animal {
  }

  class Fish: Animal {
  }

  proc Bird.fly() {
    writeln("Flying ...!");
  }

  proc Fish.swim() {
    writeln("Swimming ...!");
  }

} // module SomeAnimals


proc main() {

  use SomeAnimals;

  var anim: Animal;

  anim = new Fish();

  select (anim.type) {
  when Fish do anim.swim();
  }  
  delete anim;

  anim = new Bird();

  select (anim.type) {
  when Bird do anim.fly();
  }
  delete anim;

} // proc main

这可以编译,但是在 运行 之后,它会简单地退出而不产生任何 打印。显然,包含在 select 语句中的对 anim.swim() 和 anim.fly() 方法的调用由于某种原因没有被执行。如果不使用这些 select 语句来检查多态变量 "anim" 的实际类型,代码当然不会编译。

上面的例子实际上是一个工作的直译 使用 Fortran 的 "select type" 语句的 Fortran 2008 代码。做 Chapel 提供了类似的声明,或者这个示例是否必须以完全不同的方式编码才能在 Chapel 中工作?我在 Chapel 文档中找不到任何相关内容。

理解您的代码为何不起作用的关键是 Chapel 中的 myVar.type 指的是变量的 static 类型而不是其 dynamic 类型。因此,即使您和我都可以看到 anim 最初是 Fish,后来是 Birdanim.type 将始终是 Animal,因为它被声明为 var anim: Animal; 赋予它静态类型 Animal。您可以通过将 main() 函数更改为以下 (try it online):

来查看这一点
proc main() {
  use SomeAnimals;

  var anim: Animal;

  anim = new Fish();
  writeln(anim.type:string);

  anim = new Bird();
  writeln(anim.type:string);
} // proc main

输出将是:

Animal
Animal

在 Chapel 中推断 class 变量的动态类型的一种方法是对其应用强制转换运算符 (:),其行为类似于 C++ 中的动态强制转换。即,如果我尝试将静态类型为 Animal 的变量转换为 Fish 但它实际上是 Bird,我将返回 nil,表明 class 对象既不是 Fish 也不是 Fish.

的子 class

因此,重写您的 main() 的行为将如下所示 (try it online):

proc main() {
  use SomeAnimals;

  var anim: Animal = new Fish();

  var aFish = anim:Fish;
  if aFish then
    aFish.swim();

  delete anim;
  anim = new Bird();

  var aBird = anim:Bird;
  if aBird then
    aBird.fly();

  delete anim;
} // proc main

(我使用 shorthand if classVar ... 表示 if classVar != nil ...

回到你关于 Chapel 是否有类似 Fortran 类型的 select 语句的具体问题,目前没有。对于静态类型的推理(如 int vs. real vs. my record R vs. a subclass of C),像你一样在变量类型上使用 select 语句是完全合理的(或者你可以提供一个函数的重载,我们会根据参数的静态类型选择正确的函数)。但是对于你在 class 层次结构中工作并且必须推断对象的动态类型的情况,你的主要工具将是强制转换,如上所述,或动态调度,或在 class区分大小写(可以认为是动态转换的手动实现)。