D

D has no preprocessor, but it has a powerful template system.  Combined with pragma(msg), it is a powerful machine for generating output at compile time.

When trying these out, you should instruct the compiler to do just the compiling and not the linking.  In DMD, the -c command-line option does this.  Otherwise, you'll probably get a crash of some kind, especially with the last example.

99 Bottles of Beer

Just as I've done with the C page, I'm going to begin with a "program" to print the "99 bottles of beer" lyrics.

template bottlesOfBeer(uint n) {
    pragma(msg, toStr!(n) ~ bottleSP!(n) ~ " on the wall");
    pragma(msg, toStr!(n) ~ bottleSP!(n));
    pragma(msg, "Take one down, pass it around");
    pragma(msg, toStr!(n-1) ~ bottleSP!(n-1) ~ " on the wall");
    pragma(msg, "");
    const int bottlesOfBeer = bottlesOfBeer!(n-1);
}

template bottlesOfBeer(uint n : 0) {
    const int bottlesOfBeer = 0;
}

template bottleSP(uint n) {
    const char[] bottleSP = n == 1 ? " bottle of beer" : " bottles of beer";
}

template toStr(uint n) {
    const char[] toStr = "123456789"[n < 10 ? 0 : n/10 - 1 .. n/10]
      ~ "0123456789"[n%10 .. n%10 + 1];
}

const int dummy = bottlesOfBeer!(99);

Pascal's Triangle

const uint rows = 16;
const uint width = 5;

// Number formatting
template toStr(uint w, uint n) {
    const char[] toStr = toStr!(w-1, n/10) ~ "0123456789"[n%10 .. n%10 + 1];
}

template toStr(uint w, uint n : 0) {
    const char[] toStr = spaces!(w);
}

template spaces(uint w) {
    const char[] spaces = " " ~ spaces!(w-1);
}

template spaces(uint w : 0) {
    const char[] spaces = "";
}

// Calculating cells of Pascal's triangle
template pascal(uint row, uint col : 0) {
    const uint pascal = 1;
}

template pascal(uint row, uint col : row) {
    const uint pascal = 1;
}

template pascal(uint row, uint col) {
    const uint pascal = pascal!(row-1, col) + pascal!(row-1, col-1);
}

// Presenting the results in rows
template pascalRow(uint row) {
    const char[] pascalRow = spaces!(width * (rows - row - 1) / 2) ~
      pascalRow!(row, 0u);
}

template pascalRow(uint row, uint fromCol) {
    const char[] pascalRow = toStr!(width, pascal!(row, fromCol))
      ~ pascalRow!(row, fromCol + 1);
}

template pascalRow(uint row, uint fromCol : row) {
    const char[] pascalRow = toStr!(width, 1);
}

// Doing the whole thing
template pascalTriangle(uint fromRow) {
    pragma(msg, pascalRow!(fromRow));
    const uint pascalTriangle = pascalTriangle!(fromRow + 1);
}

template pascalTriangle(uint fromRow : rows) {
    const uint pascalTriangle = 0;
}

uint dummy = pascalTriangle!(0);

Mandelbrot Set

They get more involved than this.  With the help of D's built-in complex number type, one can write a CTP that visualises the Mandelbrot set.  Of course, the resolution is nothing compared to what you can get out of Fractint, but it works.

const real bailout = 4;
const uint iter = 20;

template image(real xMin, real yMin, real xStep, real yStep,
      uint xCount, uint yCount) {
    static if (yCount == 0) {
        const int image = 0;
        const real xZoom1 = real.nan, yZoom1 = real.nan;
        const real xZoom2 = real.nan, yZoom2 = real.nan;
    } else {
        static if (yMin <= 0) {
            /*   take the absolute value of yMin in order to use already
             *   calculated data if available
             */
            alias row!(-yMin, xMin, xStep, xCount) thisRow;
            const real yNext = -yMin - yStep, yStepNext = -yStep;
        } else {
            alias row!(yMin, xMin, xStep, xCount) thisRow;
            const real yNext = yMin + yStep, yStepNext = yStep;
        }
        pragma(msg, thisRow.row);
        alias image!(xMin, yNext, xStep, yStepNext, xCount, yCount - 1) next;

        static if (thisRow.xZoom == thisRow.xZoom) {
            const real xZoom1 = thisRow.xZoom, yZoom1 = yMin;
            const real xZoom2 = next.xZoom1, yZoom2 = next.yZoom1;
        } else {
            const real xZoom1 = next.xZoom1, yZoom1 = next.yZoom1;
            const real xZoom2 = next.xZoom2, yZoom2 = next.yZoom2;
        }
    }
}

template point(real x, real y) {
    const char point = point!(x + y*1i, x + y*1i, iter);
}

template point(creal pt, creal cur, uint itLeft) {
    const char point = cur.re * cur.re + cur.im * cur.im < bailout
      ? point!(pt,
    /*   perform eight iterations at a time to improve speed and reduce
     *   the number of template instances generated
     */
        (((cur * cur + pt) * (cur * cur + pt) + pt)
            * ((cur * cur + pt) * (cur * cur + pt) + pt) + pt)
          * (((cur * cur + pt) * (cur * cur + pt) + pt)
            * ((cur * cur + pt) * (cur * cur + pt) + pt) + pt) + pt,
        itLeft - 1) : '#';
}

template point(creal pt, creal cur, uint itLeft : 0) {
    const char point = '.';
}

template row(real y, real xMin, real xStep, uint xCount) {
    static if (xCount == 0) {
        const char[] row = "";
        const real xZoom = real.nan;
    } else {
        const char pt = point!(xMin, y);
        const real xZoom = pt == '.' ? xMin
          : row!(y, xMin + xStep, xStep, xCount - 1).xZoom;
        const char[] row = point!(xMin, y)
          ~ row!(y, xMin + xStep, xStep, xCount - 1).row;
    }
}

alias image!(-2, 1.25, 0.125, -0.125, 23, 21) image1;
pragma(msg, "");
alias image!(image1.xZoom2 - 0.125, image1.yZoom2 + 0.125,
  0.015625, -0.015625, 17, 17) image2;
pragma(msg, "");
alias image!(image2.xZoom2 - 0.015625, image2.yZoom2 + 0.015625,
  1.0/512, -1.0/512, 17, 17) image3;