Data model

Metalang99 provides four different types of collections, as well as a means for defining and dealing with compound data types. (Type checking is not performed due to performance reasons.)

Variadics

Representation: x, y, z, ....

Documentation: variadics.h.

Variadics are a comma-separated list of preprocessor tokens. Most of the time, a user will provide variadic arguments to your macro so that you could manipulate them as you want:

[examples/assert_for_each.c]

#include <metalang99.h>

#include <assert.h>

#define ASSERT_FOR_EACH(...)                                                                       \
    do {                                                                                           \
        ML99_EVAL(ML99_variadicsForEach(                                                           \
            ML99_compose(v(ML99_semicoloned), ML99_reify(v(assert))),                              \
            v(__VA_ARGS__)))                                                                       \
    } while (0)

int main(void) {
    ASSERT_FOR_EACH(123 == 123, 2 + 2 == 4, "foo"[1] == 'o');
}

Here, ASSERT_FOR_EACH accepts variadic arguments, which is communicated by its signature. Internally, it calls ML99_variadicsForEach to iterate through each argument, resulting in a number of assert(...); statements instead of one assert(a && b && ...); (which makes debugging easier because failed assertions will not be collapsed with each other).

Tuple

Representation: (x, y, z, ...).

Documentation: tuple.h.

A tuple is formed by putting variadic arguments into parentheses. Besides a collection-like usage, tuples can simulate C structures; the common pattern is to define a tuple constructor (rect below) and accessors of the corresponding fields (rectWidth and rectHeight):

[ examples/rectangle.c ]

In type theory, tuples are known as product types.

Choice

Representation: (tag, ...).

Documentation: choice.h.

A choice type encodes a set of alternatives; each alternative can be constructed by a corresponding value constructor and be inspected by the means of pattern matching:

[ examples/binary_tree.c ]

In type theory, choice types are usually referred to as sum types.

Cons-list

Representation: choice type.

Documentation: list.h.

A cons-list is represented as a choice type with two alternatives: an empty list ML99_nil() and a list constructor ML99_cons(x, xs). Cons-list is the most powerful collection:

Although cons-lists provide many more functions than any other collection, they are also more time and space-consuming. If you can deal with a native representation directly (such as variadics, tuples, or sequences), you should do so. Most of the time, a user will provide variadic arguments to your macro, and the only appropriate operation will be for-each loop (such as ML99_variadicsForEach).

However, if you still miss a certain function for native collections, you can always convert your representation to a cons-list via ML99_list, ML99_listFromSeq, etc.

Sequence

Representation: (x)(y)(z) ....

Documentation: seq.h.

A sequence is yet another fast native collection. A perfect example of using sequences is Interface99, which allows us to define a software interface like this:

With vfunc being defined as follows (simplified):

Thus, a number of vfunc invocations forms a complete sequence. Later, Interface99 works with this sequence via ML99_seqForEach and a few other helpful macros.

Last updated

Was this helpful?