Ecumenicalculator

Behold, my entry to the OMGWTF competition: Ecumenicalculator!

Screenshot of Ecumenicalculator

What makes this apparently simple program WTF-worthy? Just this: it doesn’t use numbers.

Nowhere in the backend code will you see ints, shorts, longs, floats, doubles, or any other numerical types, or any operations on them, or invocations on any functions that accept or return them. (The GUI code does use some ints, but only to the extent that they’re needed to interface with GTK to actually do the drawing, and even then it doesn’t do any math on them.)

How is this possible? Well, the code does use bools, as well as the container classes provided by the STL. And, of course, plenty of my own classes, all of which adhere to the don’t-use-numbers constraint.

OK, but how is this possible? The code uses Church numerals to represent individual digits. So, naturally, I had to implement untyped Lambda calculus in C++.

But of course, Church numerals will only give you nonnegative integers. To represent arbitrary real numbers (OK, technically, only rational numbers), I do what most humans do when writing down numbers: I make a list of digits, with each position being “worth” a different amount. There’s a radix point after the ones digit, and optionally a negative sign in front. I accomplish this mainly by putting multiple Church numerals into an std::list, maintaining an iterator after the ones digit, and a bool to flag for negative numbers.

That’s why the program is called Ecumenicalculator: it does computations on a bunch of Churches working together!

*ducks*

Needless to say, writing something like this without ever explictly using numbers provided by the language can get pretty interesting, especially when you need to do something like reference counting objects (since copying them eats up all available memory). C++ is also most definitely not a language well-suited for implementing untyped Lambda calculus.

Here’s some representative excerpts from the source code to demonstrate some of the hijinks that are going on to pull this off:

static const MyDigit radix (MyDigit ().successor ().successor ().successor ().successor ().successor ().successor ().successor ().successor ().successor ().successor ());

[calculator.cpp:39]

Well, how else are you going to get 10 when you haven’t created any other numbers yet? Compute the number after the number after the number after the number after the number after the number after the number after the number after the number after the number after zero!

typedef Curry< Curry< Curry<AddImpl> > > Add;

[church.h:235]

How can you not like recursive class template instantiation? Each Lambda expression class’s operator() only takes one argument, so when you need four arguments, you need to do some Currying. Making currying a class template lets you write the currying code once and apply it wherever you want.

Lambda result = band (iszero (sub (_numeral) (rhs._numeral))) (bnot (iszero (sub (rhs._numeral) (_numeral)))) (t) (f);

[church.cpp:173-174]

Thanks to operator(), it’s possible to write code that looks downright functional. Can you tell what that line is computing? (Hint: the variables all have obvious names.) Also, I think if I can work in five more sets of parentheses somewhere in there, I become an honorary Lisp programmer.

delete this;

[lambda.cpp:71]

You probably never want to do that unless you know what you’re doing.

If you want to see more (including recursive Lambda calculus expressions and a subtraction algorithm that guarantees you’ll never try to borrow from a zero), now that the entry deadline has passed, you can download the source for Ecumenicalculator and try it out.

The Chains! No!

I had heard about how bad the third-party Zelda games for the CD-i were, but thanks (?) to YouTube, now anyone can experience the pain themselves.

Here’s the final battle and ending of The Wand of Gamelon. There’s just so much wrong with this, it’s hard to know where to start, and it’s just a two minute clip….