Examining generated function arguments

An important point to remember is that arguments of generated functions contain data types, not actual values. The following is a visual representation of how generated functions work:

This is in sharp contrast to functions, which accept arguments as values. It is also different from macros, which accept arguments as expressions. Here, generated functions accept arguments as data types. It may seem a little strange, but let's do a simple experiment to confirm that this is indeed the case.

For this experiment, we will define the doubled function again by displaying the argument on screen before returning the expression.

@generated function doubled(x)
@show x
return :( 2 * x )
end

Let's test the function again.

As it is shown, the value of argument x is Int64 rather than 2 during the execution of the generated function. Furthermore, when the function is called again, it no longer shows the value of x. This is because the function is now compiled after the first call.

Now, let's see what happens if we run it again with a different type:

The compiler has kicked in again and compiled a new version based upon the type of Float64. So, technically speaking, we now have two versions of the doubled function for each type of argument.

You may have realized that the behavior of generated functions is similar to that of regular functions when it comes to specialization. The difference is that we have a chance to manipulate the abstract syntax tree right before the compilation happens.

With this new generated function, we can now take advantage of the hypothetical super-duper software by switching over to the faster double_super_duper function whenever the data type of the argument is a subtype of AbstractFloat, as shown in the following code:

@generated function doubled(x)
if x <: AbstractFloat
return :( double_super_duper(x) )
else
return :( 2 * x )
end
end

Using generated functions, we can specialize the function depending on the type of the argument. When the type is AbstractFloat, the function will resort to the double_super_duper(x) rather than the 2 *x expression.

As mentioned in the official Julia language reference manual, care must be taken when developing generated functions. The exact limitations are beyond of the scope of this book. You are highly encouraged to refer to the manual if you need to write generated functions for your software.

Generated functions are a useful tool to deal with cases that macros are unable to handle. Specifically, during the macro expansion process, there is no information about the types of the argument. Generated functions allow us to get a little closer to the heart of the compilation process. With the additional knowledge about argument types, we are more flexible when it comes to handling different situations.

As a metaprogramming tool, macros are used much more extensively than generated functions. Nevertheless, it is nice to know that both tools are available.

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

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