# Example of generated functions -- suitable for docs?

**URL:** <https://discourse.julialang.org/t/example-of-generated-functions-suitable-for-docs/364>\
**Category:** Internals & Design\
**Tags:** documentation\
**Created:** [November 16, 2016, 10:17pm UTC](https://discourse.julialang.org/t/example-of-generated-functions-suitable-for-docs/364 "2016-11-16T22:17:44Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [November 16, 2016, 10:17pm UTC](https://discourse.julialang.org/t/example-of-generated-functions-suitable-for-docs/364/1 "2016-11-16T22:17:44Z")

</div>

I have a good introductory example of the need for generated functions using multiplication of two objects of type `Vol{n}` type representing an n-dimensional volume (see below for the code).

This could replace the part in the Julia manual that does things that don’t need generated functions, after which we are then told “Don’t copy these examples!” ! However, I am concerned that the level of the mathematical discussion (n-dimensional volumes) might just confuse the issue. The question is thus if it is suitable for the manual?  
Of course, you can just give the code without the mathematical motivation, or replace the `+` with a `*` and treat it as a way to “put multiplication into the compile stage”.

```julia
immutable Vol{N}
    volume::Float64
end

```

Instead of

```julia
import Base.*
*{N1,N2}(V1::Vol{N1}, V2::Vol{N2}) = Vol{N1+N2}(V1.volume * V2.volume)
* (generic function with 150 methods)

```

we should use

```julia
@generated *{N1,N2}(V1::Vol{N1}, V2::Vol{N2}) = :(Vol{$(N1+N2)}(V1.volume * V2.volume))

```

to get efficient code.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [November 17, 2016, 12:37am UTC](https://discourse.julialang.org/t/example-of-generated-functions-suitable-for-docs/364/2 "2016-11-17T00:37:38Z")

</div>

What about a blogpost on generated functions where you explain the math and the code? This sounds like something I’d like to read in detail.

Though I agree that the example for generated functions should be changed in the manual. I find the current one to be a brick wall (I still haven’t used generated functions because of it, though by now I probably should have).

---

<div class="post-metadata">

**Author:** ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)\
**Post date:** [November 17, 2016, 1:58am UTC](https://discourse.julialang.org/t/example-of-generated-functions-suitable-for-docs/364/3 "2016-11-17T01:58:54Z")

</div>

Why do you think this is a good example? It doesn’t need generated functions to get multiplication of constants to happen in the compile stage (that just happens naturally without any effort on your part), while the transform that you did in the example above actually adds lots of confusing, subtle, and an unnecessary limitations. I won’t go into those here, but for example, we can just write it as:

```julia
immutable Volume
  volume::Float64
  ndims::Int
end
import Base.*
*(V1::Volume, V2::Volume) = Volume(V1.volume * V2.volume, V1.ndims + V2.ndims)

```

which has the same runtime constant-folding capability, without the memory and compile-time overhead and in many cases will generate better, more efficient code.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [November 17, 2016, 2:06am UTC](https://discourse.julialang.org/t/example-of-generated-functions-suitable-for-docs/364/4 "2016-11-17T02:06:40Z")

</div>

Even if this isn’t the right choice, I think there should be a discussion about making a new and simpler (and correct) example for the manual.

---

<div class="post-metadata">

**Author:** ![akis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/akis/32/156_2.png) [@akis](https://discourse.julialang.org/u/akis)\
**Post date:** [November 17, 2016, 2:31am UTC](https://discourse.julialang.org/t/example-of-generated-functions-suitable-for-docs/364/5 "2016-11-17T02:31:07Z")

</div>

The proposed example demonstrates how the understanding of “how something works” (here generated functions) isn’t the same with the understanding of “how something is useful”. Generated functions are a recent addition to Julia and a naturally complicated one. The author of the respective section in the manual included everything he should to cover the working part (the “Don’t copy them!” examples actually help in that effort), but the usefulness part (especially how to improve things, instead of worsening them, whether performance-wise or readability-wise etc.) has much room for improvement (only a loop unrolling example is given). However, I don’t have to offer a better alternative at the moment (I’m currently working on simpler concepts).

---

<div class="post-metadata">

**Author:** ![barche](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/barche/32/79_2.png) [@barche](https://discourse.julialang.org/u/barche)\
**Post date:** [November 17, 2016, 12:28pm UTC](https://discourse.julialang.org/t/example-of-generated-functions-suitable-for-docs/364/6 "2016-11-17T12:28:14Z")

</div>

> [@jameson](#):
>
> ```julia
> *(V1::Volume, V2::Volume) = Volume(V1.volume * V2.volume, V1.ndims + V2.ndims)
> 
> ```
> 
> which has the same runtime constant-folding capability, without the memory and compile-time overhead and in many cases will generate better, more efficient code.

How can you be sure in this case that the addition of the ndims happens at compile time? If I understood correctly, the OP example was to get compile-time computation of the dimensionality, i.e. the `N1 + N2`?

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [November 17, 2016, 3:46pm UTC](https://discourse.julialang.org/t/example-of-generated-functions-suitable-for-docs/364/7 "2016-11-17T15:46:37Z")

</div>

My example was too abbreviated. The other part of it is that you should only be able to add two `Vol` objects if they have the same dimension:

```julia
+{n}(V1::Vol{n}, V2::Vol{n}) = Vol{n}(V1.volume + V2.volume)

```

In my actual use case, this is tightly coupled to actual objects that are N-dimensional, whose volume you are taking. The compiler will then actually be able to know at compile time what the dimensions all are.

---

<div class="post-metadata">

**Author:** ![hpoit](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hpoit/32/245_2.png) [@hpoit](https://discourse.julialang.org/u/hpoit)\
**Post date:** [April 8, 2017, 7:28am UTC](https://discourse.julialang.org/t/example-of-generated-functions-suitable-for-docs/364/8 "2017-04-08T07:28:44Z")

</div>

An example of generated functions is _very_ suitable for Docs Julia for sure, especially now that I am trying to understand what has been generated in Tensorflow.jl. David, we welcome you!

---

<div class="post-metadata">

**Author:** ![fengyang.wang](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fengyang.wang/32/104_2.png) [@fengyang.wang](https://discourse.julialang.org/u/fengyang.wang)\
**Post date:** [April 12, 2017, 9:26pm UTC](https://discourse.julialang.org/t/example-of-generated-functions-suitable-for-docs/364/9 "2017-04-12T21:26:29Z")

</div>

A generated function is not necessary in this situation. A `Base.@pure` function would suffice.

```julia
struct Vol{N}
    volume::Float64
end

Base.@pure producttype{N1,N2}(::Type{Vol{N1}}, ::Type{Vol{N2}}) = Vol{N1 + N2}
import Base.*
x::Vol * y::Vol = producttype(typeof(x), typeof(y))(x.volume * y.volume)

```

Admittedly, I don’t fully understand the criteria needed for a function to be `@pure`; perhaps @jameson can confirm that this is correct.
