@@ -872,49 +872,52 @@ entirely in Julia. You can read their source and see precisely what they
872
872
do — and all they do is construct expression objects to be inserted into
873
873
your program's syntax tree.
874
874
875
- Staged functions
875
+ Generated functions
876
876
----------------
877
877
878
- *Staged functions * play a similar role as macros, but at a later stage
879
- between parsing and run-time. Staged functions give the capability to
880
- generate specialized code depending on the types of their arguments.
881
- While macros work with expressions at parsing-time and cannot access the
882
- types of their inputs, a staged function gets expanded at a time when
883
- the types of the arguments are known, but the function is not yet compiled.
878
+ A very special macro is ``@generated ``, which allows you to define so-called
879
+ *generated functions *. These have the capability to generate specialized
880
+ code depending on the types of their arguments with more flexibility and/or
881
+ less code than what can be achieved with multiple dispatch. While macros
882
+ work with expressions at parsing-time and cannot access the types of their
883
+ inputs, a generated function gets expanded at a time when the types of
884
+ the arguments are known, but the function is not yet compiled.
884
885
885
- Depending on the types of the arguments, a staged function returns a quoted
886
- expression which then forms the function body of the specialized function.
887
- Thus, staged functions provide a flexible framework to move work from
888
- run-time to compile-time.
886
+ Depending on the types of the arguments, a generated function returns a
887
+ quoted expression which then forms the method body of the specialized
888
+ method. Thus, generated functions provide a flexible framework to move
889
+ work from run-time to compile-time.
889
890
890
- When defining staged functions, there are three main differences to
891
+ When defining generated functions, there are three main differences to
891
892
ordinary functions:
892
893
893
- 1. You use the keyword ``stagedfunction `` instead of ``function ``
894
+ 1. You annotate the function declaration with the ``@generated `` macro.
895
+ This adds some information to the AST that lets the compiler know that
896
+ this is a generated function.
894
897
895
- 2. In the body of the `` stagedfunction `` you only have access to the
898
+ 2. In the body of the generated function you only have access to the
896
899
*types * of the arguments, not their values.
897
900
898
901
3. Instead of calculating something or performing some action, you return
899
- from the staged function a *quoted expression * which, when evaluated,
900
- does what you want.
902
+ from a *quoted expression * which, when evaluated, does what you want.
901
903
902
- It's easiest to illustrate this with an example. We can declare a staged
904
+ It's easiest to illustrate this with an example. We can declare a generated
903
905
function ``foo `` as
904
906
905
907
.. doctest ::
906
908
907
- julia> stagedfunction foo(x)
909
+ julia> @generate foo(x)
908
910
println(x)
909
911
return :(x*x)
910
912
end
911
913
foo (generic function with 1 method)
912
914
913
- Note that the body returns a quoted expression, namely ``x*x ``.
915
+ Note that the body returns a quoted expression, namely ``:(x*x) ``, rather
916
+ than just the value of ``x*x ``.
914
917
915
918
From the callers perspective, they are very similar to regular functions;
916
- in fact, you don't have to know if you're calling a `` function `` or a
917
- `` stagedfunction `` - the syntax and result of the call is just the same.
919
+ in fact, you don't have to know if you're calling a regular or generated
920
+ function or a - the syntax and result of the call is just the same.
918
921
Let's see how ``foo `` behaves:
919
922
920
923
.. doctest ::
@@ -929,10 +932,10 @@ Let's see how ``foo`` behaves:
929
932
julia> y
930
933
"barbar"
931
934
932
- So, we see that in the body of the `` stagedfunction `` , ``x `` is the
933
- *type * of the passed argument, and the value returned by the `` stagedfunction ``,
934
- is the result of evaluating the quoted expression we returned from the
935
- definition, now with the *value * of ``x ``.
935
+ So, we see that in the body of the generated function , ``x `` is the
936
+ *type * of the passed argument, and the value returned by the generated
937
+ function, is the result of evaluating the quoted expression we returned
938
+ from the definition, now with the *value * of ``x ``.
936
939
937
940
What happens if we evaluate ``foo `` again with a type that we have already
938
941
used?
@@ -942,29 +945,29 @@ used?
942
945
julia> foo(4)
943
946
16
944
947
945
- Note that there is no printout of ``Int64 ``. The body of the `` stagedfunction ``
946
- is only executed *once * (not entirely true, see note below) when the method
947
- for that specific set of argument types is compiled. After that, the
948
- expression returned from the `` stagedfunction `` on the first invocation
948
+ Note that there is no printout of ``Int64 ``. The body of the generated
949
+ function is only executed *once * (not entirely true, see note below) when
950
+ the method for that specific set of argument types is compiled. After that,
951
+ the expression returned from the generated function on the first invocation
949
952
is re-used as the method body.
950
953
951
- The reason for the disclaimer above is that the number of times a staged
952
- function is staged is really an implementation detail; it *might * be only
954
+ The reason for the disclaimer above is that the number of times a generated
955
+ function is generated is really an implementation detail; it *might * be only
953
956
once, but it *might * also be more often. As a consequence, you should
954
- *never * write a staged function with side effects - when, and how often,
957
+ *never * write a generated function with side effects - when, and how often,
955
958
the side effects occur is undefined. (This is true for macros too - and just
956
- like for macros, the use of `eval ` in a staged function is a sign that
959
+ like for macros, the use of `eval ` in a generated function is a sign that
957
960
you're doing something the wrong way.)
958
961
959
- The example staged function ``foo `` above did not do anything a normal
962
+ The example generated function ``foo `` above did not do anything a normal
960
963
function ``foo(x)=x*x `` could not do, except printing the the type on the
961
- first invocation and incurring a higher compile-time cost. However, the
962
- power of a staged function lies in its ability to compute different quoted
964
+ first invocation ( and incurring a higher compile-time cost) . However, the
965
+ power of a generated function lies in its ability to compute different quoted
963
966
expression depending on the types passed to it:
964
967
965
968
.. doctest ::
966
969
967
- julia> stagedfunction bar(x)
970
+ julia> @generated function bar(x)
968
971
if x <: Integer
969
972
return :(x^2)
970
973
else
@@ -978,27 +981,30 @@ expression depending on the types passed to it:
978
981
julia> bar("baz")
979
982
"baz"
980
983
984
+ (although of course this contrived example is easily implemented using
985
+ multiple dispatch...)
986
+
981
987
We can, of course, abuse this to produce some interesting behavior::
982
988
983
- julia> stagedfunction baz(x)
989
+ julia> @generated function baz(x)
984
990
if rand() < .9
985
991
return :(x^2)
986
992
else
987
993
return :("boo!")
988
994
end
989
995
end
990
996
991
- Since the body of the staged function is non-deterministic, its behavior
997
+ Since the body of the generated function is non-deterministic, its behavior
992
998
is undefined; the expression returned on the *first * invocation will be
993
999
used for *all * subsequent invocations with the same type (again, with the
994
- exception covered by the disclaimer above). When we call the staged
1000
+ exception covered by the disclaimer above). When we call the generated
995
1001
function with ``x `` of a new type, ``rand() `` will be called again to
996
1002
see which method body to use for the new type. In this case, for one
997
1003
*type * out of ten, ``baz(x) `` will return the string ``"boo!" ``.
998
1004
999
1005
*Don't copy these examples! *
1000
1006
1001
- These examples are hopefully helpful to illustrate how staged functions
1007
+ These examples are hopefully helpful to illustrate how generated functions
1002
1008
work, both in the definition end and at the call site; however, *don't
1003
1009
copy them *, for the following reasons:
1004
1010
@@ -1009,7 +1015,7 @@ copy them*, for the following reasons:
1009
1015
the same thing, but it is both simpler and faster.
1010
1016
* the `baz ` function is pathologically insane
1011
1017
1012
- Instead, now that we have a better understanding for how staged functions
1018
+ Instead, now that we have a better understanding for how generated functions
1013
1019
work, let's use them to build some more advanced functionality...
1014
1020
1015
1021
An advanced example
@@ -1043,46 +1049,46 @@ thing: a runtime loop over the dimensions of the array, collecting the
1043
1049
offset in each dimension into the final index.
1044
1050
1045
1051
However, all the information we need for the loop is embedded in the type
1046
- information of the arguments. Thus, we can utilize staged functions to
1047
- move the iteration to compile-time; in compiler parlance, we use staged
1052
+ information of the arguments. Thus, we can utilize generated functions to
1053
+ move the iteration to compile-time; in compiler parlance, we use generated
1048
1054
functions to manually unroll the loop. The body becomes almost identical,
1049
1055
but instead of calculating the linear index, we build up an *expression *
1050
1056
that calculates the index::
1051
1057
1052
- stagedfunction sub2ind_staged {N}(dims::NTuple{N}, I::Integer...)
1058
+ @generated function sub2ind_gen {N}(dims::NTuple{N}, I::Integer...)
1053
1059
ex = :(I[$N] - 1)
1054
1060
for i = N-1:-1:1
1055
1061
ex = :(I[$i] - 1 + dims[$i]*$ex)
1056
1062
end
1057
1063
return :($ex + 1)
1058
1064
end
1059
1065
1060
- **What code will this staged function generate? **
1066
+ **What code will this generate? **
1061
1067
1062
1068
An easy way to find out, is to extract the body into another (regular)
1063
1069
function::
1064
1070
1065
- stagedfunction sub2ind_staged {N}(dims::NTuple{N}, I::Integer...)
1066
- sub2ind_staged_impl (dims, I...)
1071
+ @generated function sub2ind_gen {N}(dims::NTuple{N}, I::Integer...)
1072
+ sub2ind_gen_impl (dims, I...)
1067
1073
end
1068
1074
1069
- function sub2ind_staged_impl {N}(dims::NTuple{N}, I...)
1075
+ function sub2ind_gen_impl {N}(dims::NTuple{N}, I...)
1070
1076
ex = :(I[$N] - 1)
1071
1077
for i = N-1:-1:1
1072
1078
ex = :(I[$i] - 1 + dims[$i]*$ex)
1073
1079
end
1074
1080
return :($ex + 1)
1075
1081
end
1076
1082
1077
- We can now execute ``sub2ind_staged_impl `` and examine the expression it
1083
+ We can now execute ``sub2ind_gen_impl `` and examine the expression it
1078
1084
returns::
1079
1085
1080
- julia> sub2ind_staged_impl ((Int,Int), Int, Int)
1086
+ julia> sub2ind_gen_impl ((Int,Int), Int, Int)
1081
1087
:(((I[1] - 1) + dims[1] * ex) + 1)
1082
1088
1083
1089
So, the method body that will be used here doesn't include a loop at all
1084
1090
- just indexing into the two tuples, multiplication and addition/subtraction.
1085
- All the looping is performed compile-time, and we avoid looping during execution
1086
- entirely. Thus, we only loop *once per type *, in this case once per `` N ``
1087
- (except in edge cases where the function is staged more than once - see
1088
- disclaimer above).
1091
+ All the looping is performed compile-time, and we avoid looping during
1092
+ execution entirely. Thus, we only loop *once per type *, in this case once
1093
+ per `` N `` (except in edge cases where the function is generated more than
1094
+ once - see disclaimer above).
0 commit comments