November 01, 2010 Immutable struct fields | ||||
---|---|---|---|---|
| ||||
To answer the recent D.learn thread "How would I optimize this parser?", I have tried to find a more efficient way to build the parse tree, so I have used tagged structs, something like this: enum NodeType { node, text, tag } struct Node { /*immutable*/ NodeType type = NodeType.node; Node* parent; } struct TextNode { /*immutable*/ NodeType type = NodeType.text; Node* parent; string content; public nothrow this(string content) { this.content = content; } } struct TagNode { /*immutable*/ NodeType type = NodeType.tag; Node* parent; string name; Node*[] children; public nothrow this(string name) { this.name = name; } public nothrow void addChild(Node* newChild) { children ~= newChild; newChild.parent = cast(Node*)&this; } } Each struct instance contains a "type" tag that at runtime tells what kind of node it is. This tag never changes in the life of a node, so it's better for it to be immutable, to use the type system to avoid changing it by mistake. But unfortunately it doesn't work, this is a reduced example: struct Foo { immutable int x = 1; } struct Bar { immutable int x = 2; } static assert(Foo.sizeof == 4); void main() { Foo f; assert(f.x == 1); assert((cast(Bar)f).x == 1); } It seems that immutable fields act like static const fields or enum fields, they have no storage. This seems a little weird to me. Do you know a way to put immutable storage in a struct instance? Using this doesn't work: this(int) { type = NodeType.tag; } And a static this() doesn't seem to work. So in the program I have just used a mutable type field, but it looks silly... Bye, bearophile |
November 01, 2010 Re: Immutable struct fields | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 02.11.2010 0:24, bearophile wrote: > To answer the recent D.learn thread "How would I optimize this parser?", I have tried to find a more efficient way to build the parse tree, so I have used tagged structs, something like this: > > > enum NodeType { node, text, tag } > > struct Node { > /*immutable*/ NodeType type = NodeType.node; > Node* parent; > } > > struct TextNode { > /*immutable*/ NodeType type = NodeType.text; > Node* parent; > string content; > > public nothrow this(string content) { > this.content = content; > } > } > > struct TagNode { > /*immutable*/ NodeType type = NodeType.tag; > Node* parent; > string name; > Node*[] children; > > public nothrow this(string name) { > this.name = name; > } > > public nothrow void addChild(Node* newChild) { > children ~= newChild; > newChild.parent = cast(Node*)&this; > } > } > > > Each struct instance contains a "type" tag that at runtime tells what kind of node it is. This tag never changes in the life of a node, so it's better for it to be immutable, to use the type system to avoid changing it by mistake. > > But unfortunately it doesn't work, this is a reduced example: > > > struct Foo { > immutable int x = 1; > } > struct Bar { > immutable int x = 2; > } > static assert(Foo.sizeof == 4); > void main() { > Foo f; > assert(f.x == 1); > assert((cast(Bar)f).x == 1); > } > > > It seems that immutable fields act like static const fields or enum fields, they have no storage. This seems a little weird to me. Do you know a way to put immutable storage in a struct instance? > > Using this doesn't work: > > this(int) { type = NodeType.tag; } > > And a static this() doesn't seem to work. So in the program I have just used a mutable type field, but it looks silly... > > Bye, > bearophile Wierd indeed, best workaround I can come up with: struct Foo { immutable int x; private this(int val){ x = val; } public static Foo opCall(){ return Foo(1); } } struct Bar { immutable int x; private this(int val){ x = val; } public static Bar opCall(){ return Bar(2); } } static assert(Foo.sizeof == 4); void main() { Foo f = Foo(); assert(f.x == 1); assert((cast(Bar*)&f).x == 1); } works, and the fact that static opCall is deprecated(?) makes me wish it's a compiler bug. And you still could shoot yourself in the leg, but only explicitly (that is "Foo f = Foo(42)" ) and only in the same module. -- Dmitry Olshansky |
Copyright © 1999-2021 by the D Language Foundation