Добавление значения в общую коллекцию в классе не разрешено из-за области действия
У меня возникают проблемы при добавлении элементов в объект, который хранит коллекцию значений общего типа. Я пробовал минимальный рабочий пример, который вызывает ошибку:
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
$
Как правильно добавить что-то в общую структуру данных, подобную этой? Как я поступаю об этом неправильно?
1 ответ
Здесь есть два возможных подхода, в зависимости от того, какое поведение вы хотите:
"Я хочу, чтобы моя коллекция стала владельцем объектов Обезьяны"
В этом случае вы захотите создать экземпляр OneElementQueue
коллекция для хранения owned Monkey
объекты, а не просто [borrowed] Monkey
объекты, которые по умолчанию для типов классов. Вы можете сделать это с одной строкой изменения (попробуйте онлайн):
var q = new owned OneElementQueue(owned Monkey);
В этом подходе, передавая owned Monkey
на ваш add()
Метод передает владение аргументу и, в конечном итоге, коллекции, делая исходную ссылку на объект недействительной (nil
).
"Я хочу, чтобы моя коллекция заимствовала существующие объекты Обезьяны, не принимая их в собственность"
В этом случае вам нужно сообщить add()
метод, которым аргумент, переданный в него, переживет сам аргумент (и затем будет уверен, что не лжет об этом). В версии 1.19 Chapel это можно сделать с помощью аннотаций на весь срок службы:
proc add(element : eltType) lifetime element > this {
где аннотация lifetime element > this
утверждает, что фактический аргумент прошел через element
переживет this
сама коллекция, поэтому компилятор не должен бояться, что заимствование прекратится, как только появится формальный аргумент.
Пожизненные аннотации не были доступны в Chapel 1.18, поэтому, если вы используете эту версию, вам нужно использовать немного больший молоток и применить pragma "unsafe"
к методу. Обратите внимание, что прагмы не являются официально поддерживаемой функцией и могут измениться в будущем, поэтому в этом случае она служила временным ограничением до тех пор, пока не были реализованы аннотации времени жизни (попробуйте онлайн):
pragma "unsafe"
proc add(element : eltType) {