Hacker News new | ask | show | jobs
by Tegran 4529 days ago
> And there's no simple excuse for the preprocessor; I don't know exactly why that exists, but my guess is that back in the 1970s it was an easy way to get at least an approximation to several desirable language features without having to complicate the actual compiler.

Clearly this guy has never had to deal with a large, complicated code base in C. Dismissing the preprocessor as a crutch for a weak compiler shows a significant ignorance about the useful capabilities that it brings.

4 comments

I assume when he says "no simple excuse", it's more pointing to the massive problems that the mere existence of the macro pre-processor introduces for reasoning about the text of any C or C++ program, for programmers, tools, and compilers.

I've worked in a code base where, tucked away in a shared header file somewhere up the include chain, a programmer had added the line

#define private public

(because he wanted to do a bunch of reflection techniques on some C++ code, IIRC, and the private keyword was getting in his way)

Now regardless of whether that's a good idea, if you are reading C or C++ code, you always have to be aware, for any line of code you read, of the possibility that someone has done such a thing. Hopefully not, but unless you have scanned every line of every include file included in your current context recently, as well as every line of code preceding the current one in the file you're reading, you just can't know. Clearly this makes giant headaches for compliation and tools, as well.

So yeah, of course every mid to large C / C++ program uses the macro pre-processor extensively. You can do useful things with it, and there's no way to turn it off and not use it, anyway, given the way includes work in C / C++, so you might as well take advantage of it.

But it's not an accident that more recent languages have dropped that particular feature.

Even C# has limited preprocessor functionality:

http://msdn.microsoft.com/en-us/library/ed8yd1ha.aspx

The only time I have seen actual conditional compilation used in C# was hilarious - I was given a pile of code that had preprocessor directives used to make private methods public so that they could be unit tested. However, if you switched the compile time flag to the "production" state nothing compiled....

He wrote PuTTY and all of the assorted tools. I'd say that's a fairly large codebase.

Also, one of the main reasons Go was created was that the authors were tired of the compile times caused largely by preprocessing.

And he wrote a Collection of Puzzle games that work across different operating systems including Android: http://www.chiark.greenend.org.uk/~sgtatham/puzzles/

I would say Simon Tatham definitely has good experience in programming.

I doubt he meant that it was not useful, rather that the usefulness might have been better served as a function of the compiler rather than some disconnected transformation tool.

Of course this thought process would eventual bring you down the road of macros systems such as those in Lisps, but that's going to be more difficult with a language lacking homoiconicity of code and data.

It's just unfairly easy in Lisp :)

There are macros in many non-homoiconinc languages (eg. Rust, Dylan), and there are add-ons for several of the languages lacking them (eg. SweetJS for Javascript, MacroPy for Python).

You should have a look at Simon's preprocessor-based coroutines (as used inside PuTTY) http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html and his more elaborate techniques for metaprogramming custom control structures in C http://www.chiark.greenend.org.uk/~sgtatham/mp/