Friday, March 4, 2011

The Problem with Atoms

First: What is an "Atom" (and what is it good for)?
In Erlang, an Atom is a special kind of constant. A constant that could be used without defining it elsewhere and that's identified by the syntax (all lower-case or enclosed in single quotes):

Printer = spawn(...),
Printer ! { do_print, "hello world" },

The spawned actor now might match on the atom do_print:

    { do_print, What } -> ...

Atoms are a way to "tag", resp. to structure tuples / messages. And this approach is far better than abuse some integer values ("enums").

My last post was about Pattern Matching in C++. We do match on the types first, so Atoms should have distinct types. Those types should be declared while they are used. That's what templates are for. But what's the template parameter(s)? const char* is obviously a bad choice. String literals could not be used as template parameters and the workaround (declare a string with external linkage) does not solve the problem of distinct types. But variadic templates (char...) do.

If we translate the example above, it might look like this:

template<char... Name>
class atom { ... };


auto printer = spawn(...);
printer.send(atom<"do_print">, "hello world");


receive(on<atom<"do_print">, std::string>() >> ... );

Well... That's not valid C++(0x). Unfortunately!
Although I'm not the only one who would love to see this to become valid C++. But it's not in the current working draft.

By the way, this is how it would be accepted by the compiler:

auto printer = spawn(...);
printer.send(atom<'d','o','_','p','r','i','n','t'>, "hello world");

Would you disagree if I say this is ridiculous? I guess not.
But what's the next best we can do? Maybe a user defined suffix:

template<char... Name>
atom<Name...> operator "" _atom();

auto printer = spawn(...);
printer.send(do_print_atom, "hello world");


receive(on<decltype(do_print_atom), std::string>() >> ... );

It's far better then giving a list of characters, but decltype(...) is annoying (and verbose). And I couldn't test it, because user-defined literals are not implemented by any compiler by now (GCC, clang, VisualStudio, Comeau, ...).

I'm afraid that I'm forced to skip atoms until user-defined literals are available (or my favorite solution becomes legal in a future draft version).

No comments:

Post a Comment