Boost logo

Boost :

From: John Max Skaller (skaller_at_[hidden])
Date: 2001-08-21 15:46:16


Douglas Gregor wrote:

> > If we're going to enshrine variants in C++,
> > they should be done properly: by an extension
> > to the core language.
> [snip 'adding features to core' discussion]
>
> I might as well feed the flames a bit... I'm not sure I agree that there is
> any reason to add variants into the core C++ language.

        I'm not either. To be clear, I'm completely sure that
a decent language requires the at least one representation
of the fundamental and dual algebraic data types corresponding
to products and sums: structs and discriminated unions.
Some languages provide two products (tuples and records,
using ordering and naming).

        However, it isn't clear if it is worth 'fixing' C++.

> With a little bit of
> work I was able to come up with syntax similar to the above.
>
> variant<int, double, std::string, etc> v;
> variant_switch(v)
> .on<std::string>(print_string())
> .on<int>(print_int())
> .on_default(print_unknown());
>
> These variants are efficient and typesafe. Am I missing some key feature that
> would require language support?

        I'm not sure. What does 'print_string()' print?
Is this a method call on the object of the type given in the
.on<T> pattern? How is this parsed by existing C++ compilers?

        Next: variants must be tagged.
They discriminate on the tag, NOT on the data type. There can be two
variants of the same type, and there might be no type.

        An example of the first case (in ML syntax):

        type money = Debit of decimal | Credit of decimal

The data type in both cases is decimal, but debits and credits are
different (and treated differently by the accounting system).

        An example of the second case: the C enum is precisely
a discriminated union of variants with no data:

        enum trankind {Debit, Credit}

is written in ML as

        type trankind = Debit | Credit

Now, to be fair, you can provide the discrimination using your
system using a wrapper type. For example:

        template<class Tag, class X>
        struct tagged { X x; };

        struct Credit {};
        struct Debit {};
        tagged<Credit,int>
        tagged<Debit,int>

which would even work (with a specialisation) for X==void.
[Using a type this way is a well known template meta
programming hack: does it have a name??]

However, ML variants may also be recursive:

        type list = Cons of int * list | Empty

In C++, you'd have to use a pointer:

        struct node {
                int x;
                tagged<Cons,node> *next;
        }

        tagged<Cons, node>
        tagged<Empty> // dflts to void, and specialisation

so that works too.

So using the tagging hack, it is possible to convert the
'in principle wrong' type discrimination into
'in principle correct' tagged discrimination.

If you're using method calls, then, yes, the result
would be typesafe (although I don't quite understand
how this would work using existing C++ syntax).

So:
        1. It lacks compile time completion assurance.
        2. It would break the open/closed principle:

you'd have to program a method for each match,
in ML you can use a 'free function'. That's a very
serious objection, since encapsulation is not
desirable here.

In fact, object orientation was _invented_ precisely
to get around the incorrect use of variants for
abstraction. But that doesn't mean ALL uses of
variants are ill founded, it simply means that both
mechanisms are needed. Most OO languages threw out
all the good things in structured programming:
variants and nesting, and the result is just as bad,
if not worse, than the original paradigm -- as
the reemergence of Functional programming is showing.

Note: perhaps I misunderstood your intent.

>(Note: the max number of allowed types in a
> variant will be dependent on a macro as soon as the PREPROCESSOR library is
> available, so that doesn't count).

        Accepted: this is a different issue.

-- 
John (Max) Skaller, mailto:skaller_at_[hidden] 
10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850
New generation programming language Felix  http://felix.sourceforge.net
Literate Programming tool Interscript     
http://Interscript.sourceforge.net

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk