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

时间:2018-02-21 02:55:09

标签: 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),如上例所示?

此外,处理诸如"通常"等变量是没有问题的。变量,例如,将它们作为参数传递给其他函数或将它们包含在类/记录的字段中? (如果它们过于宽泛,请忽略后面这些问题...)如果存在潜在的陷阱(如果有的话),我将不胜感激。

2 个答案:

答案 0 :(得分:3)

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

虽然在1.16及更高版本中使用了一流函数,但您可以期待重新审视该领域的语言设计。特别是目前对于是否可以捕获变量的问题没有合理的答案(现在尝试这样做可能会导致混淆错误)。但我不知道将来会在哪个版本中发生变化。

关于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();

答案 1 :(得分:2)

是的,在您的示例中,您使用的是Chapel的initial support for first-class functions。对于第二个问题,您也可以使用function type helper来声明函数数组:

var myfuncs: [1..2] func(int);

这些第一类函数对象可以作为参数传递给函数 - 这就是Futures.async()的工作方式 - 或存储为记录(Try It Online! example)中的字段。 Chapel的一流功能还包括lambda functions

要明确的是,这种支持的“初始”方面带有警告(来自文档):

  

在我们开发并实现更强大的故事之前,应该将此机制视为权宜之计技术,这就是为什么它在本自述文件而不是语言规范中进行描述。