Using generated functions

So far, we have explained how to create macros that return expression objects. Since macros work at the syntax level, they can manipulate code only by examining how it looks. However, Julia is a dynamic system where data types are determined at runtime. For that reason, Julia provides the ability to create generated functions, which allow you to examine data types for a function call and return an expression, just like macros. When an expression is returned, it will be evaluated at the call site.

To understand why generated functions are needed, let's revisit how macros work. Let's say we have created a macro that doubles the value of its arguments. It would look like the following:

macro doubled(ex)
return :( 2 * $(esc(ex)))
end

No matter what expression we pass into this macro, it would just blindly rewrite the code so it doubles the original expression. Suppose that one day, a super-duper piece of software is developed that lets us calculate twice the amount of a floating-point number quickly. In this case, we may want the system to switch to that function for floating-point numbers only, instead of using the standard multiplication operator.

So our first attempt might be to try something as follows:

# This code does not work. Don't try it.
macro doubled(ex)
if typeof(ex) isa AbstractFloat
return :( double_super_duper($(esc(ex))) )
else
return :( 2 * $(esc(ex)))
end
end

But unfortunately, it is impossible for macros to do this. Why? Again, macros only have access to the abstract syntax tree. This is at the earlier part of the compilation pipeline and there is no type information available. The ex variable in the preceding code is merely an expression object. This problem can be solved with generated functions. Keep on reading!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.71.211