Three Unlikely Successful Features of D

Rene Zwanenburg renezwanenburg at gmail.com
Tue Mar 20 18:41:26 PDT 2012


On Tuesday, 20 March 2012 at 19:02:16 UTC, Andrei Alexandrescu 
wrote:
> I plan to give a talk at Lang.NEXT 
> (http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2012) with 
> the subject above. There are a few features of D that turned 
> out to be successful, in spite of them being seemingly 
> unimportant or diverging from related consecrated approaches.
>
> What are your faves? I have a few in mind, but wouldn't want to 
> influence answers.
>
>
> Thanks,
>
> Andrei

I've seen most of D's cool features mentioned, but I believe 
nobody mentioned mixins yet. Mixins are messy to maintain, but 
together with CTFE they can be used to create some really neat 
code if used properly.

One of the first things I wrote while learning D is a vector 
class. In GLSL vectors can be 'swizzled', for example:
vec3(1, 2, 3).zyx == vec3(3, 2, 1);
Swizzles are often useful in graphics or physics code. I don't 
know of any non-shading language that allows me to use swizzle 
syntax. As the following code shows, it's quite easy to do in D:


module main;

import std.stdio;
import std.process;
import std.conv;


int main(string[] argv) {
   alias Vec!4 Vec4;
   Vec4 v = Vec4(1, 2, 3, 4);

   writeln(v.bgra); // Prints Vec!(4)([3, 2, 1, 4])
   writeln(v.rg); // Prints Vec!(2)([1, 2])

   return 0;
}

private immutable (char[][]) elementNames = [['x', 'y', 'z', 
'w'], ['r', 'g', 'b', 'a'], ['s', 't', 'p', 'q']];

struct Vec(size_t size) {
   alias size Size;

   mixin(generateConstructor(Size));

   mixin(generateProperties(Size));

   auto opDispatch(string s)() {
     mixin(generateSwizzle(s));
   }

   float v[Size];
}

private string generateConstructor(size_t size) {
   string constructorParams;
   string constructorBody;

   foreach(i; 0..size) {
     string paramName = "v" ~ to!string(i);
     constructorParams ~= "float " ~ paramName ~ "=0,";
     constructorBody ~= "v[" ~ to!string(i) ~ "] = " ~ paramName ~ 
";";
   }

   return "this(" ~ constructorParams[0..$-1] ~ "){" ~ 
constructorBody ~ "}";
}

private string generateProperties(size_t size) {
   string props;

   foreach(names; elementNames) {
     foreach(i, name; names[0..size]) {
       props ~= "@property float " ~ name ~ "() const { return v[" 
~ to!string(i) ~ "]; }";
       props ~= "@property void " ~ name ~ "(float f) { v[" ~ 
to!string(i) ~ "] = f; }";
     }
   }

   return props;
}

private string generateSwizzle(string elements) {
   string swizzleImpl = "return Vec!" ~ to!string(elements.length) 
~ "(";

   foreach(e; elements) {
     swizzleImpl ~= e ~ ",";
   }

   return swizzleImpl[0..$-1] ~ ");";
}



More information about the Digitalmars-d mailing list