Voldemort Types In D Sometimes, the confluence of existing features can yield unexpected surprises.



Sometimes, the confluence of existing features can yield unexpected surprises. While I'd like to think that we designed Voldemort Types into the D programming language, the reality is that they were discovered by Andrei Alexandrescu. What are Voldemort Types? Read on.

First, a bit of background.

An InputRange in D is a type with the following members:

front - get the first element of the range popFront - remove the first element of the range empty - are there more elements in the range?

which form the basis of iteration. Just for fun, let's design an InputRange that will return a sequence of random numbers, forever. (We can also call this a generator.)

It can look like this (not a very good random number generator, but it'll do for the moment):

module rnd; struct RandomNumberGenerator { this(uint seed) { next = seed; popFront(); // get it going } @property int front() { return ((next / 0x10000) * next) >> 16; } void popFront() { next = next * 1103515245 + 12345; } @property bool empty() { return false; } private: uint next; }

and a function that'll return it:

RandomNumberGenerator generator(uint seed) { return RandomNumberGenerator(seed); }

and a lovely program that will print out 10 such numbers:

import std.stdio; import rnd; void main() { int count; foreach (n; generator(5)) { writeln(n); if (++count == 10) break; } }

and the result is:

26298 25347 52004 26314 22713 9193 9426 118 36355 10786

That's where one would normally stop. But there's just something annoying about it. All I really care about is the rnd.generator function, but yet there's this type RandomNumberGenerator sitting out there by itself. It just looks like a failure of encapsulation, as it is leaking outside of my generator abstraction.

I could mark it with the private attribute and modules other than rnd won't be able to access it. But it's still there, outside the scope of where it belongs, and other module members can still access it, private or not (in D, private declarations are not hidden from other declarations within the same module). Besides, I want it to be so clean it squeaks.