June 24, 2004
Apropos is basically a bunch of unrelated, but generally useful stuff I wind up writing either because I need it or (as is far more frequently the case) because it amuses me to do so.

http://andy.tadan.us/d/apropos-23-june-2004.zip

Most notable is the variadic print(...) and format(...) functions, which are meant to be simple enough that they can just be used without much thought.

There's also a Variant type which can hold pretty much anything for later regurgitation. (ie 'box' non-class types)

Gratuitiously syntax-highlighted sample code:
http://andy.tadan.us/d/apropos.d.html

Questions/comments/suggestions/indifference are welcome.

 -- andy
June 28, 2004
Andy Friesen wrote:
> Apropos is basically a bunch of unrelated, but generally useful stuff I wind up writing either because I need it or (as is far more frequently the case) because it amuses me to do so.
> 
> http://andy.tadan.us/d/apropos-23-june-2004.zip
> 
> Most notable is the variadic print(...) and format(...) functions, which are meant to be simple enough that they can just be used without much thought.
> 
> There's also a Variant type which can hold pretty much anything for later regurgitation. (ie 'box' non-class types)
> 
> Gratuitiously syntax-highlighted sample code:
> http://andy.tadan.us/d/apropos.d.html

I've updated Apropos again.  It can be downloaded at
<http://andy.tadan.us/d/apropos-27-june-2004.zip>

The only real change is the addition of tuples and the parser library.

Tuples are typesafe, heterogenious sequences of arbitrary values.  Boost implements something like this for C++ as well.  This exists mainly to prove that it can be done with a sensible interface despite D's lack of template argument deduction.  It's also a relatively good gauntlet for the template engine. :)

The parser library is the summation of everything Walter thinks is wrong about operator overloading. :)

Parsers are small classes which can be strung together with copiously overloaded operators to create complex string parsers with a tiny amount of code.  The concept came from the Boost.Spirit parser library which does much the same thing, though it does so with frightening template machinations rather than simple polymorphism.

    const char[] digits = "0123456789";
    Parser parseDigit = parseAny(digits); // parses any digit
    Parser parseInt = flatten(parseDigit++); // parses one or more digits.  flatten() turns the results from the individual characters into a single string.

    // Parse results are generally trees composed of nested parse
    // results.  flatten()... flattens those trees. :)
    // There is also a discard() filter which can be used to
    // prune unwanted results from the parse tree.

    // parse a printf-like format token
    Parser parseFormatString =
        // >> matches a sequence of parsers
        parse('%') >>         // match a '%' symbol, nothing else
        parseInt[0 .. 1] >>   // match 0 or 1 integers
        parseAny("cdiouxXeEfgGnps")
    ;

    // sample data
    InputSource stream = new StreamReader(new MemoryStream("%8d"));

    ParseResult result = parseFormatString.parse(stream);
    if (failed(result)) {
        ...
    } else {
        ...
    }

 -- andy