Chapel 中的函数变量和函数数组

标签 function chapel

在下面的代码中,我尝试通过将函数名称视为通常的变量来创建一个“函数指针”和一个函数数组:

proc myfunc1() { return 100; }
proc myfunc2() { return 200; }

// a function variable?
var myfunc = myfunc1;
writeln( myfunc() );

myfunc = myfunc2;
writeln( myfunc() );

// an array of functions?
var myfuncs: [1..2] myfunc1.type;

writeln( myfuncs.type: string );

myfuncs[ 1 ] = myfunc1;
myfuncs[ 2 ] = myfunc2;

for fun in myfuncs do
    writeln( fun() );

这似乎按预期工作(使用 Chapel v1.16)

100
200
[domain(1,int(64),false)] chpl__fcf_type_void_int64_t
100
200

所以我想知道上述函数变量的用法是否合法?为了创建函数数组,通常是先定义一个具有所需签名的具体函数,然后引用其类型(使用 .type),如上面的示例所示?

此外,将此类变量视为“通常”变量是否没有问题,例如,将它们作为参数传递给其他函数或将它们包含为类/记录的字段? (如果后面的问题太宽泛,请忽略它们......)如果存在潜在的陷阱(如果有),我将不胜感激任何建议。

最佳答案

此代码使用一流的函数支持,这是 Chapel 语言设计中的原型(prototype)/草案。您可以在First-class Functions in Chapel中阅读有关原型(prototype)支持的更多信息。技术说明。

虽然 1.16 及更高版本中可以使用许多一流函数,但您可以预期该领域的语言设计将被重新审视。特别是,对于是否可以捕获变量的问题,目前还没有合理的答案(现在尝试这样做可能会导致令人困惑的错误)。不过,我不知道 future 哪个版本会改变这种情况。

关于myfunc1.type部分,我在技术说明中提到的“指定一等函数的类型”部分提出了一种替代策略。不过,在这种情况下,我认为使用 myfunc1.type 没有任何问题。

最后,请注意,当前编译器中的 lambda 支持实际上是通过使用 this 方法创建一个类来运行的。因此,您可以做同样的事情 - 创建一个“函数对象”(借用 C++ 术语) - 具有相同的效果。 “函数对象”可以是记录或类。如果它是一个类,您可以使用继承来创建一个对象数组,这些对象可以根据其动态类型响应相同的方法。此策略可能允许您使用一流函数解决当前问题。即使一流的函数支持已经完成,“函数对象”方法也允许您更明确地了解捕获的变量。特别是,您可以将它们存储为类中的字段,并将它们设置在类初始值设定项中。以下是创建和使用不同类型函数对象数组的示例:

class BaseHandler {
  // consider these as "pure virtual" functions
  proc name():string { halt("base name called"); }
  proc this(arg:int) { halt("base greet called"); }
}
class HelloHandler : BaseHandler {
  proc name():string { return "hello"; }
  proc this(arg:int) { writeln("Hello ", arg); }
}
class CiaoHandler : BaseHandler {
  proc name():string { return "ciao"; }
  proc this(arg:int) { writeln("Ciao ", arg); }
}

proc test() {
  // create an array of handlers
  var handlers:[1..0] BaseHandler;
  handlers.push_back(new HelloHandler());
  handlers.push_back(new CiaoHandler());

  for h in handlers {
    h(1); // calls 'this' method in instance
  }
}

test();

关于Chapel 中的函数变量和函数数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48897504/

相关文章:

chapel - 如何在 Chapel 中的域上执行就地 `expand`

创建线程 - 传递参数

python - 递归检测数字是否为阶乘

enums - 如何在 Chapel 中声明 ENUM?

chapel - 是否可以在记录中为泛型类型声明 LinkedList 字段?

chapel - bool 是否有 writef() 格式说明符?

chapel - 在 Chapel 中的未知类型数组上声明一个函数?

javascript - 在 JavaScript 中声明函数

PostgreSQL 错误 : invalid input syntax for integer: "1e+06"

JavaScript默认函数值