Coffeescript and C Macros: Clean and Fast

Anyone who programs in C uses pre-processor macros to keep the code clean, maintainable and sometimes to improve run-time performance. You can use the same C pre-processor to include macros in Coffeescript or Javascript code, and it is easy!

The coffeescript file needs to be renamed with .c extension before running it thrrough gcc; otherwise, it gives a warning and doesn’t run the pre-processor. There may be some option to force it compile without checking the extension.

cp [source.coffe] [source.c]
gcc -E [source.c] > [processed.coffee]

Examples #

Improve performance #

This is the code with macros. It compares the time taken to calculate the sum of squares, using functions and macros.

square = (x) -> x * x

#define SQUARE(x) (x * x)

total = 0
console.time "no macro"
for i in [0...100000]
 total += square i
console.timeEnd "no macro"
console.log "Total #{total}"

total = 0

console.time "macro"
for i in [0...100000]
 total += SQUARE(i)

console.timeEnd "macro"
console.log "Total #{total}"

Compiled code:

# 1 "macro.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "macro.c"
square = (x) -> x * x



total = 0
console.time "no macro"
for i in [0...100000]
 total += square i
console.timeEnd "no macro"
console.log "Total #{total}"

total = 0

console.time "macro"
for i in [0...100000]
 total += (i * i)

console.timeEnd "macro"
console.log "Total #{total}"

Output:

no macro: 2ms
Total 333328333350000
macro: 1ms
Total 333328333350000

Debugging #

You can use you favorite DEBUG macro to define LOGS, and even __LINE__ and __FILE__

#define DEBUG

#ifdef DEBUG
#define LOG(x) console.log __LINE__ + ": " + (x)
#else
#define LOG(x)
#endif

n = 3
LOG("Root of #{n} = #{Math.sqrt(n)}")

There is a slight problem because # is used for comments in Coffeescript. All you need to do is to use ## instead of a single # when you want to add a comment.

#define DEBUG

##This is a comment

#ifdef DEBUG
## Define LOG macro
## Print line number
#define LOG(x) console.log __LINE__ + ": " + (x)
#else
#define LOG(x)
#endif

n = 3
LOG("Root of #{n} = #{Math.sqrt(n)}")
 
29
Kudos
 
29
Kudos

Now read this

Coffeescript helpers for d3.js

fp.js is a tiny library to help keep d3.js dom manipulation code clean. Update (December 29, 2013) # Upgraded to support the format at the bottom. Check out this rewrite of the d3.js Grouped Bar Chart Example using fp.js. I write a lot... Continue →