Interesting usage of recursive mixins and interpolation sequence parametrization for repeating code

WB witold.baryluk at gmail.com
Mon Sep 29 20:57:48 UTC 2025


I just discovered quite an interesting technique for writing code 
that needs to be repeated / interleaved / vectorized.

It uses a clever recursive mixin, where first mixin generating 
function receives a string, that is to be used as interpolation 
sequence inside that function, and then interpolates it (and 
constructs that interpolation sequence string using interpolation 
string - that part is optional tho).


It is handy.

```d

   @attribute("flatten")
   KV*[4] GetWithHash4(const ref K k0, H hash0, const ref K k1, H 
hash1, const ref K k2, H hash2, const ref K k3, H hash3) {
     static enum N = 4;

     KV*[4] ret;

     static string repeat_i(string pattern)() {
       string ret;
       import std.conv : to, text;
       foreach (i_; 0 .. N) {
         const string i = i_.to!string;
         ret ~= mixin(i"i\"$(pattern)\"".text).text;
         // ret ~= mixin(i"i\"$(pattern)\".text".text);  // also 
works.
       }
       return ret;
     }

     mixin(repeat_i!"bool r$(i)_search = true;");
     ulong todo_count = N;
     mixin(repeat_i!"auto slot_idx$(i) = hash$(i) % 
slots.length;");
     while (todo_count != 0) {
       mixin(repeat_i!"Slot* slot$(i) = &slots[slot_idx$(i)];");
       asm { "" ::: "memory"; };
       mixin(repeat_i!"auto slot$(i)_hash = slot$(i).hash_;");
       asm { "" ::: "memory"; };

       mixin(repeat_i!q{
           if (r$(i)_search) {
             if (slot$(i)_hash == hash$(i)) {
               if (slot$(i).kv.k == k$(i)) {
                 ret[$(i)] = &slot$(i).kv;
                 r$(i)_search = false;
                 todo_count--;
               }
             } else if (slot$(i)_hash == EMPTY) {
               r$(i)_search = false;
               todo_count--;
             } else {
               slot_idx$(i) = (slot_idx$(i) + 1) % slots.length;
             }
           }
         });
     }

     return ret;
   }

```


The interleaving technique here, I call software threading 
(similar to hyper-threading / SMT on CPUs, running multiple 
context in parallel). I used it in the past using C macros, maybe 
10 years ago, for similar effect. But in D, it actually is nicer 
to achieve.

Purposes of the code above are not that important, but I thought 
it might be interesting sharing the double mixin with double 
interpolation technique for building code, without a need for 
extra functions. And quite compact and readable code.

The iteration over integers / string here is trivial to extend to 
other options, like arrays, for other code generation purposes.




More information about the Digitalmars-d mailing list