由于范围原因,不允许向 class 中的通用集合添加值

Adding value to generic collection in class not allowed because of scope

我在向保存通用类型值集合的对象中添加元素时遇到问题。我尝试了一个导致错误的最小工作示例:

class OneElementQueue {

    type eltType;

    var elements : [0..0] eltType;

    //initializer
    proc init(type eltType) {
        this.eltType = eltType;
    }

    proc add(element : eltType) {
        this.elements[0] = element;
    }

    proc remove() : eltType {
        return this.elements[0];
    }   
} //end of OneElementQueue

class Monkey {

    var name: string;
    var age: int;

    proc init(name : string, age : int) {
        this.name = name;
        this.age = age;
    }

} //end of class Monkey


var q = new owned OneElementQueue(Monkey);
var m = new owned Monkey("Kyle", 6);
q.add(m);

当我尝试编译所有这些时,出现错误:

$ chpl BadQueue.chpl
BadQueue.chpl:12: In function 'add':
BadQueue.chpl:13: error: Scoped variable would outlive the value it is set to
BadQueue.chpl:12: note: consider scope of element
$

向这样的通用数据结构添加内容的正确方法是什么?我怎么弄错了?

这里有两种可能的方法,具体取决于您想要的行为:

"I want to have my collection take ownership of the Monkey objects"

在这种情况下,您需要实例化 OneElementQueue 集合来存储 owned Monkey 个对象,而不是简单地 [borrowed] Monkey 个对象,后者是 class 的默认设置类型。您可以通过一行更改 (Try it Online):

来做到这一点
var q = new owned OneElementQueue(owned Monkey);

在这种方法中,将 owned Monkey 传递给您的 add() 方法会将所有权传递给参数并最终传递给集合,从而使原始对象引用无效 (nil) .

"I want to have my collection borrow the existing Monkey objects without taking ownership of them"

在这种情况下,您需要告诉 add() 方法传递给它的参数将比参数本身更有效(然后确保不要撒谎)。在 Chapel 1.19 版本中,这可以通过生命周期注解来完成:

proc add(element : eltType) lifetime element > this {

其中注释lifetime element > this断言通过element传递的实际参数将比this集合本身存在,所以编译器不应该担心借用一次就会不复存在正式论证有。

Chapel 1.18 中不提供生命周期注解,因此如果您使用的是该版本,则需要使用稍大的锤子并将 pragma "unsafe" 应用于该方法。请注意,pragma 不是官方支持的功能,将来可能会更改,因此对于这种情况,在实现生命周期注释之前用作权宜之计 (Try it Online):

pragma "unsafe"
proc add(element : eltType) {