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 
         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 

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