Remix.run Logo
WalterBright 2 days ago

A lot of people disagree with me on that. Wait till they try to get other people to understand their code :-/

Me, I've eliminated nearly all the use of macros from my old C code that is still around. The code is better.

I suspect that heavy use of macros is why Lisp has never become mainstream.

kazinator 2 days ago | parent [-]

Heavy use of macros could be why C went mainstream.

Macros gave C efficient inline functions without anything having to be done in the compiler.

Doing things like "#define velocity(p) (p)->velocity" would instantly give a rudimentary C compiler with no inline functions a performance advantage over a crappy Pascal or Modula compiler with no inline functions, while keeping the code abstract.

And of course #if and #ifdef greatly help with situations where C does not live up to its poorly deserved portability reputation. In languages without #ifdef, you would have to clone an entire source file and write it differently for another platform, which would cause a proliferation due to minor differences (e.g. among Unixes).

Ah, speaking of which; C's #ifdef allowed everyone to have their own incompatible flavor of Unix with its own different API's and header files, yet get the same programs working.

An operating system based on a language without preprocessing would have hopelessly fragmented if treated the same way, or else stagnated due to discouraging local development.

Thanks in part to macros, Lisp people were similarly able to use each other code (or at least ideas) in spite of working on different dialects at different sites.

WalterBright 2 days ago | parent [-]

You're quite right in that early C was a primitive compiler, and adding a macro processor was a cheap and easy way to add power.

Using the macro preprocessor to work around some fundamental issues with the language is not what I meant.

I meant devising one's own language using macros. The canonical example:

    #define BEGIN {
    #define END }
We laugh about that today, but the 80's people actually did that. Today's macros are often just more complicated attempts at the same thing.

The tales I hear about Lisp is that a team's code is not portable to another team, because they each invent their own macro language in order to be able to use Lisp at all.

lor_louis a day ago | parent | next [-]

To be fair, I'd rather type BEGIN instead of <<? Or whatever the trigraph is supposed to be. We tend to forget that a lot of computers didn't have the keys to type "mathematical" symbols.

WalterBright a day ago | parent [-]

EBCDIC was already dead in the 1980s. Nobody ever used the trigraphs except for one company that hung on for years until even the C++ community decided enough was enough and dumped them.

Besides, what people wrote was:

    #define BEGIN {
not:

    #define BEGIN <<?
kazinator a day ago | parent | prev [-]

Stephen Bourne used such macros in the Bourne Shell sources to make the code resemble Algol.

The source is very clear and readable.

WalterBright a day ago | parent [-]

Have you adopted his macros in your own projects?

kazinator a day ago | parent [-]

No because even if I could identify a benefit to these macros (which I can't in the contexts in which I work) there's a cost to using them.

Macros whuch simply transliterate tokens to other tokens without performing a code transformation do not have a compelling technical benefit. Only a non-technical benefit to a peculiar minority of users.

In terms of cost, the readability and writeability are fine. What's not fine is that the macros will confuse tooling which processes C code without necessarily expanding it through the preprocessor. Tooling like text editing modes,identifier cross-referencers and whatnot.

I've used C macros to extend a language with constructs like exception handling. These have a syntax that harmonizes with the language, making then compatible with all the tooling I use.

There's a benefit because the macro expansions are too verbose and detailed to correctly repeat by hand, not to mention to correctly update if the implementation is adjusted.