
Doug McIlroy
littering the code with #ifdefs
Bonus points for keeping the #ifdefs centralized
Littering is the right word. "Bonus" is merely less negative points.
It is ironic that the beautiful Haskell should progress by adopting the worst feature of C. #ifdef is a sticking-plaster for non-portable code. It is inserted at global level, usually to effect changes at the bottom of the code hierarchy. (Maybe in Haskell it should be a monad, in competition with IO for the outermost layer.)
Plan 9 showed the way out of ifdef, by putting (non-ifdef-ed) inescapably nonportable code, such as endianity, in compilation units and #include files in a distinct part of the file system tree selected by the shell.
Another trick is to use plain if rather than #if or #ifdef, and let the compiler optimize away the unwanted side of the branch.
In any event, #ifdef is, as Simon evidently agrees, telling evidence of non-portability. It is hard to imagine an uglier "solution" to keeping up with the drip-drip-drip of Haskell evolution.
By the nature of the problem -- that is, because we want to isolate the compiler as much as possible -- the conditionalization must be performed as a separate pass. The conclusion is that some sort of pre-processor is inevitable. The remainder of the available choice space is about how ugly this pre-processor must be -- and indeed, CPP tends towards the undesirable end of the spectrum. As an example of the opposite end, consider Common Lisp, which: 1. reifies READ as the third processing phase (macroexpansion[1] and actual compilation being the other two) 2. operates at expression granularity 3. makes the full power of the language available to support the decision process of what subexpressions are available in which contexts As a rough example of how this works: http://clhs.lisp.se/Body/24_abaa.htm I don't know how much of Common Lisp preachery the list have suffered over the years, but I can't help but find this uniformity between the three parts of the language very appealing: - syntax-level of READ - macro-level of MACROEXPAND - semantics-level of the post-MACROEXPAND part of EVAL Maybe, just maybe, Haskell could borrow something from that.. -- с уважениeм / respectfully, Косырев Серёга -- 1. Macroexpansion is actually defined by the ANSI CL standard to be a part of minimal compbilation, but for the purposes of illustration it makes sense to distinguish between them.