In Julia, why is @printf a macro instead of a function?

In Julia, the syntax to print a formatted string is as follows:

@printf("Hello %d\n", 5)

Why is @printf a macro instead of a function? Is it so that it can accept a varying number of arguments?


Solution 1:

Taking a variable number of arguments is not a problem for normal Julia functions [1]. @printf is a macro so that it can parse and interpret the format string at compile time and generate custom code for that specific format string. People may not realize that C's printf function re-parses and re-interprets the format string each time you call printf. The fact that it's as fast as it is represents a minor miracle of insane pointer programming. Seriously, just look at your nearest libc's printf implementation. It's completely nuts.

Julia uses a different approach: @printf is a macro which translates format strings into efficient code specific to that format specification. If you think about it, a printf-style format string is really just a way to express a function that takes a fixed number and type of arguments and prints them in a particular way. Note that I said that the format string is a function, not printf itself, which is conceptually a function generator, turning formats into formatters. The fact that this is all crammed into a run-time function in C is a bit of a mismatch due to that being the only reasonable option in C. In fact, because of this, until very recently, it was rather easy to shoot yourself in the foot by passing the wrong number or type of arguments to C's printf. This is only better now because compilers have been special-cased to understand the semantics of printf formats.

In theory, Julia's @printf can be made faster than C since it generate's custom code, but in practice, I had a hard enough time matching C, let alone beating it. But I think that's due to the current design of our I/O system and how I'm using it, not an inherent limitation. The I/O stuff is due for an overhaul though, and when that happens, we might actually be able to beat C at formatted printing by leveraging the fact that @printf is a macro.

Solution 2:

It is for performance. The printf macro takes a constant format string (eg. "Hello %d\n") and generates optimized code for that string.