VARUNA JAYASIRI

@vpj

Coffeescript Macros

December 9, 2013

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](http://coffeescript.org/) 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 `function`s 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)}")
///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](http://coffeescript.org/) 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. ```bash 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 `function`s and macros. ```coffeescript 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: ```javascript # 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__` ```coffeescript #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. ```coffeescript #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)}")