Skip to content

Commit

Permalink
docs: fix up generated function examples in metaprogramming.md (#51386)
Browse files Browse the repository at this point in the history
The last example was untested and has been non-functional actually.
  • Loading branch information
aviatesk authored Sep 19, 2023
1 parent 22a0276 commit 7f37e70
Showing 1 changed file with 38 additions and 30 deletions.
68 changes: 38 additions & 30 deletions doc/src/manual/metaprogramming.md
Original file line number Diff line number Diff line change
Expand Up @@ -1340,8 +1340,7 @@ julia> function sub2ind_loop(dims::NTuple{N}, I::Integer...) where N
ind = I[i]-1 + dims[i]*ind
end
return ind + 1
end
sub2ind_loop (generic function with 1 method)
end;
julia> sub2ind_loop((3, 5), 1, 2)
4
Expand Down Expand Up @@ -1380,8 +1379,7 @@ julia> @generated function sub2ind_gen(dims::NTuple{N}, I::Integer...) where N
ex = :(I[$i] - 1 + dims[$i] * $ex)
end
return :($ex + 1)
end
sub2ind_gen (generic function with 1 method)
end;
julia> sub2ind_gen((3, 5), 1, 2)
4
Expand All @@ -1392,20 +1390,21 @@ julia> sub2ind_gen((3, 5), 1, 2)
An easy way to find out is to extract the body into another (regular) function:

```jldoctest sub2ind_gen2
julia> @generated function sub2ind_gen(dims::NTuple{N}, I::Integer...) where N
return sub2ind_gen_impl(dims, I...)
end
sub2ind_gen (generic function with 1 method)
julia> function sub2ind_gen_impl(dims::Type{T}, I...) where T <: NTuple{N,Any} where N
length(I) == N || return :(error("partial indexing is unsupported"))
ex = :(I[$N] - 1)
for i = (N - 1):-1:1
ex = :(I[$i] - 1 + dims[$i] * $ex)
end
return :($ex + 1)
end
sub2ind_gen_impl (generic function with 1 method)
end;
julia> @generated function sub2ind_gen(dims::NTuple{N}, I::Integer...) where N
return sub2ind_gen_impl(dims, I...)
end;
julia> sub2ind_gen((3, 5), 1, 2)
4
```

We can now execute `sub2ind_gen_impl` and examine the expression it returns:
Expand Down Expand Up @@ -1434,25 +1433,34 @@ To solve this problem, the language provides syntax for writing normal, non-gene
alternative implementations of generated functions.
Applied to the `sub2ind` example above, it would look like this:

```julia
function sub2ind_gen(dims::NTuple{N}, I::Integer...) where N
if N != length(I)
throw(ArgumentError("Number of dimensions must match number of indices."))
end
if @generated
ex = :(I[$N] - 1)
for i = (N - 1):-1:1
ex = :(I[$i] - 1 + dims[$i] * $ex)
end
return :($ex + 1)
else
ind = I[N] - 1
for i = (N - 1):-1:1
ind = I[i] - 1 + dims[i]*ind
end
return ind + 1
end
end
```jldoctest sub2ind_gen_opt
julia> function sub2ind_gen_impl(dims::Type{T}, I...) where T <: NTuple{N,Any} where N
ex = :(I[$N] - 1)
for i = (N - 1):-1:1
ex = :(I[$i] - 1 + dims[$i] * $ex)
end
return :($ex + 1)
end;
julia> function sub2ind_gen_fallback(dims::NTuple{N}, I) where N
ind = I[N] - 1
for i = (N - 1):-1:1
ind = I[i] - 1 + dims[i]*ind
end
return ind + 1
end;
julia> function sub2ind_gen(dims::NTuple{N}, I::Integer...) where N
length(I) == N || error("partial indexing is unsupported")
if @generated
return sub2ind_gen_impl(dims, I...)
else
return sub2ind_gen_fallback(dims, I)
end
end;
julia> sub2ind_gen((3, 5), 1, 2)
4
```

Internally, this code creates two implementations of the function: a generated one where
Expand Down

0 comments on commit 7f37e70

Please sign in to comment.