Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Glad you like it! Not sure what separator you would pick between the name(args)=expansion stuff. I could imagine some generic files/modules might have enough or long enough params that people might want to backslash line continue. So, maybe '@' or '`' { depending on if you want many or few pixels ;-) } ?

    #include "file.c" _(_x)=myNamePrefix ## _x `\
                      KEY=charPtr VAL=int `\
                      ....
The idea being that inside any generic module your private / protected names are all spelled _(_add)(..).

By doing that kind of namespacing, you actually can write a generic module which allows client code manual instantiators a lot of control to select "verb noun" instead of "noun verb" kinds of schemes like "add_word" instead of "word_add" and potentially even change snake_case to camelCase with some _capwords.h file that does `#define _get Get` like moves, though of course name collisions can bite. That bst/ thing I linked to does not have full examples of all the optionality. E.g., to support my "stack popping" of macro defs, without that but just with ANSI C 89 you might do something like this instead to get "namespace nesting":

    #ifndef CT_ENVIRON_H
    #define CT_ENVIRON_H
    /* This file establishes a macro environment suitable for instantiation of
       any of the Map/Set/Seq/Pool or other sorts of generic collections. */
    
    #ifndef _
    /* set up a macro-chain using token pasting *inside* macro argument lists. */
    #define _9(x)    x    /* an identity macro must terminate the chain. */
    #define _8(x) _9(x)
    #define _7(x) _8(x)   /* This whole chain can really be as long as   */
    #define _6(x) _7(x)   /* you want.  At some extreme point (maybe     */
    #define _5(x) _6(x)   /* dozens of levels) expanding _(_) will start */
    #define _4(x) _5(x)   /* to slow-down the Cpp phase.                */
    #define _3(x) _4(x)   /* Also, definition order doesn't matter, but  */
    #define _2(x) _3(x)   /* I like how top->bottom matches left->right  */
    #define _1(x) _2(x)   /* in the prefixing-expansions.               */
    #define _0(x) _1(x)
    #define _(x)  _0(x)   /* _(_) must start the expansion chain */
    #endif
    
    #ifndef CT_LNK
    #   define CT_LNK static
    #endif
    #endif /* CT_ENVIRON_H */
and then with a setup like that in place you can do:

    #define _8(x) _9(i_ ## x)  /* some external client decides "i_"          */
    _(_foo)                    /* #include "I" -> i_foo at nesting-level 8   */
    #define _6(x) _7(e_ ## x)  /* impl of i_ decides "e_"                    */
    _(_foo)                    /* #include "E" -> i_e_foo at level 6         */
    #define _3(x) _4(c_ ## x)  /* impl of e_ decides "c_"                    */
    _(_foo)                    /* #include "C" -> i_e_c_foo at level 3       */
    #define _0(x) _1(l_ ## x)  /* impl of c_ decides "l_"                    */
    _(_t)
    _(_foo)                    /* #include "L" -> i_e_c_l_foo at level 0     */
    #define _0(x) _1(x)        /* c impl uses _(l_foo) to define _(bars)     */
    _(_foo)                    /* i_e_c_foo at nesting level 3 again         */
    #define _3(x) _4(x)        /* e impl uses _(c_foo) to define _(bars)     */
    _(_foo)                    /* i_e_foo at nesting level 6 again           */
    #define _6(x) _7(x)        /* i impl now uses _(e_foo) to define _(bars) */
    _(_foo)                    /* i_foo at nesting level 8 again             */
Yes, yes. All pretty hopelessly manual (as is C in so many aspects!). But that smarter macro def semantics across parameterized includes I mentioned above could go a long way towards a quality of life improvement "for client code" with good "library code" file organization. I doubt it will ever be easy enough to displace C++ much, though.

Personally, I started doing this kind of thing in the mid-1990s as soon as I saw people shipping "code in headers" in C++ template libraries and open source taking off. These days I think of it as an example of how much you can achieve with very simple mechanisms and the trade-offs of automating instantiation at all. But people sure seem to like to "just refer" to instances of generic types.



Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: