Consider the classic assert
macro:
#define assert(x) if(!(x)) { throw new Error("Assertion failed: " + #x) }
This macro allows one to use a very natural syntax,
assert(status != 'dead')
let's say, and still get a
meaningful error message when the assertion fails. If you wanted
to do this in pure Javascript, you'd either just have a regular
assert
function check whether its argument is true,
in which case you won't have a meaningful error message, or
you'd use something like this:
assert(function() { return x })
and have the assert
function call the passed-in
function. If it returns false, assert
could
decompile the passed-in function and use the code to construct
an error messge. That approach, however, is verbose, ugly, and
delicate (not all browsers support function decompilation).
Another approach would be to just call assert
with a string giving the error message to use. But who wants
to repeat himself? Using an assert
macro with the
C preprocessor provides a way to use a simple syntax that
always does the right thing.
Also, a assert
macro can be
#ifdef
ed away, so it can have no effect on
production code.
Function calls in Javascript can have a significant overhead, though that's somewhat ameliorated by next-generation Javascript engines. Embedding a calculation inside a macro allows you to avoid a function call while not having to create an unmaintainable cut-and-paste mess. For example, consider:
#define ISCCW(P0, P1, P2) \ ((P1.x - P0.x) * (P2.y - P0.y) > (P2.x - P0.x) * (P1.y - P0.y))which checks whether a triangle is wound counterclockwise. Some algorithms check this property hundreds of times, and making it a function call would add significant overhead.
It's important to send as little
code to the client as possible. It's often worthwhile to step
debugging functions, testcases, and documentation from code sent
to the client. While JS minifiers strip some unnecessary bytes by
eliminating comments and whitespace, they have no way of knowing
which segments of actual code are unnecessary. With the C preprocessor, however,
you can juse #ifdef
away code not used for production.
#ifdef DEBUG function my_test_func() { ... } #endif // DEBUG
In order to sent pre-processed Javascript, your server must pre-process the file before sending it to the client. Most of the advantages of pre-processing are lost if you have to do it manually.
Just configure your web server to pipe Javascript through GNU cpp:
/usr/bin/cpp -P -undef -Wundef -std=c99 -nostdinc -Wtrigraphs -fdollars-in-identifiers -Cbefore minifying and compressing it for transmission.