Efficient way to create/copy immutable struct instance with modified data
Adam D Ruppe
destructionator at gmail.com
Fri Nov 19 18:11:01 UTC 2021
On Friday, 19 November 2021 at 17:38:53 UTC, Merlin Diavova wrote:
> I'm trying to figure out the most efficient way to create
> modified instances of immutable structs.
This might not be the best way but it is a kinda cool trick
anyway: structs have a `tupleof` property you can slice. So you
can do things like:
Node(old_node.tupleof[0 .. argIndex], replacement,
old_node.tupleof[argIndex + 1 .. $]);
Where argIndex can be like 0 to replace the first item in the
struct, or 1 to replace the second.
It is possible to look this up using reflection and kinda
automate this if you wanted.
```
mixin template Replaceable() {
// returns a replaced thing when you use it as
`with_someField`
typeof(this) opDispatch(string s, T)(T replacement)
if(s.length > 5 && s[0 .. 5] == "with_")
{
static foreach(idx, member; typeof(this).tupleof)
{
static if(__traits(identifier, member) ==
s[5 .. $])
enum argIndex = idx;
}
// if the arg is not found you will get an ugly
error message here about undefined
// argIndex.... meh.
return typeof(this)(this.tupleof[0 .. argIndex],
replacement, this.tupleof[argIndex + 1 .. $]);
}
}
immutable struct Node {
string label;
Node* parentNode;
int port;
mixin Replaceable; // add the ugly generic code from the
top
}
void main() {
Node i = Node("one", null, 4);
Node i2 = i.with_port(6); // and now use it like this
assert(i2.label == "one");
assert(i2.port == 6);
}
```
I did `with_` instead of camelCase to avoid having to mess with
case comparisons on the name.
More information about the Digitalmars-d-learn
mailing list