在运行时填充 array/assoc 不可变对象数组
Filling an array/assoc array of immutable objects at runtime
是否可以在运行时在 D 中填充不可变对象的数组或关联数组?我有一组不可变的定义,其数据在运行时从外部源读取。每个定义还包含几个其他不可变对象的数组。但是,编译器似乎禁止使用循环实例化不可变数组。在这个例子中(字段数据简化):
immutable class Definition {
string name;
int size;
immutable(Field)[string] fields;
immutable class Field {
int num;
this (int num) {
this.num = num;
}
}
this(string name, int size) {
this.name = name;
this.size = size;
foreach (i; 0..size) {
string key = [cast(char)('a' + i)]; // a, b, c...
auto field = new immutable(Field)(i);
fields[key] = field; // ERROR
}
}
}
class Instance {
Definition def;
void speak() {
writefln("I am currently referencing definition '%s' (%d)", def.name, def.size);
}
}
auto defA = new immutable(Definition)("AAA", 4);
auto defB = new immutable(Definition)("BBB", 6);
auto instance = new Instance();
instance.def = cast(Definition) defA;
instance.speak();
instance.def = cast(Definition) defB;
instance.speak();
我收到 错误:不可变字段 'fields' 在循环中或在标签 之后不允许初始化。有没有办法解决这个问题,或者有更好的方法来实现它?还是我做错了?
您需要使用辅助函数和临时函数。
--- test.d 2015-04-11 12:03:54.257670300 +0000
+++ test2.d 2015-04-11 12:03:59.433170300 +0000
@@ -1,3 +1,4 @@
+import std.exception;
import std.stdio;
immutable class Definition {
@@ -14,11 +15,13 @@
this(string name, int size) {
this.name = name;
this.size = size;
+ immutable(Field)[string] fields;
foreach (i; 0..size) {
string key = [cast(char)('a' + i)]; // a, b, c...
auto field = new immutable(Field)(i);
- fields[key] = field; // ERROR
+ add(fields, key, field);
}
+ this.fields = fields.assumeUnique();
}
}
class Instance {
@@ -38,3 +41,9 @@
instance.def = cast(Definition) defB;
instance.speak();
}
+
+void add(K, V)(V[K] aa, K k, V v)
+{
+ assert(k !in aa);
+ cast()aa[k] = cast()v;
+}
是否可以在运行时在 D 中填充不可变对象的数组或关联数组?我有一组不可变的定义,其数据在运行时从外部源读取。每个定义还包含几个其他不可变对象的数组。但是,编译器似乎禁止使用循环实例化不可变数组。在这个例子中(字段数据简化):
immutable class Definition {
string name;
int size;
immutable(Field)[string] fields;
immutable class Field {
int num;
this (int num) {
this.num = num;
}
}
this(string name, int size) {
this.name = name;
this.size = size;
foreach (i; 0..size) {
string key = [cast(char)('a' + i)]; // a, b, c...
auto field = new immutable(Field)(i);
fields[key] = field; // ERROR
}
}
}
class Instance {
Definition def;
void speak() {
writefln("I am currently referencing definition '%s' (%d)", def.name, def.size);
}
}
auto defA = new immutable(Definition)("AAA", 4);
auto defB = new immutable(Definition)("BBB", 6);
auto instance = new Instance();
instance.def = cast(Definition) defA;
instance.speak();
instance.def = cast(Definition) defB;
instance.speak();
我收到 错误:不可变字段 'fields' 在循环中或在标签 之后不允许初始化。有没有办法解决这个问题,或者有更好的方法来实现它?还是我做错了?
您需要使用辅助函数和临时函数。
--- test.d 2015-04-11 12:03:54.257670300 +0000
+++ test2.d 2015-04-11 12:03:59.433170300 +0000
@@ -1,3 +1,4 @@
+import std.exception;
import std.stdio;
immutable class Definition {
@@ -14,11 +15,13 @@
this(string name, int size) {
this.name = name;
this.size = size;
+ immutable(Field)[string] fields;
foreach (i; 0..size) {
string key = [cast(char)('a' + i)]; // a, b, c...
auto field = new immutable(Field)(i);
- fields[key] = field; // ERROR
+ add(fields, key, field);
}
+ this.fields = fields.assumeUnique();
}
}
class Instance {
@@ -38,3 +41,9 @@
instance.def = cast(Definition) defB;
instance.speak();
}
+
+void add(K, V)(V[K] aa, K k, V v)
+{
+ assert(k !in aa);
+ cast()aa[k] = cast()v;
+}