# How to define an everywhere defined function within a function

**URL:** <https://discourse.julialang.org/t/how-to-define-an-everywhere-defined-function-within-a-function/25044>\
**Category:** General Usage\
**Tags:** parallel\
**Created:** [June 7, 2019, 1:28pm UTC](https://discourse.julialang.org/t/how-to-define-an-everywhere-defined-function-within-a-function/25044 "2019-06-07T13:28:59Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![dkarrasch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dkarrasch/32/7410_2.png) [@dkarrasch](https://discourse.julialang.org/u/dkarrasch)\
**Post date:** [June 7, 2019, 1:28pm UTC](https://discourse.julialang.org/t/how-to-define-an-everywhere-defined-function-within-a-function/25044/1 "2019-06-07T13:28:59Z")

</div>

In my package, I’d like to offer a convenience function like this:

```julia
function gaussian(σ::Real=1.0)
    @eval function (x)
        exp(-abs2(x) / $(float(4σ)))
    end
end

```

I want the `@eval` because I don’t want the `4σ` to be computed at every evaluation

```julia
kernel = gaussian(3.0)
kernel(0.2)

```

After a long while, I realized that `kernel` is not defined on all workers, and seemingly neither

```julia
@everywhere kernel = gaussian(3.0)

```

nor putting `@everywhere` in the definition of `gaussian` helps. Something that works with ordinary variables also doesn’t work

```julia
@everywhere kernel = $kernel

```

because Julia claims to not know what to interpolate on the r.h.s. (UndefVarError). How can I both keep the convenience of calling a function-generating function and have the resulting function defined everywhere?

---

<div class="post-metadata">

**Author:** ![StefanKarpinski](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefankarpinski/32/24_2.png) [@StefanKarpinski](https://discourse.julialang.org/u/StefanKarpinski)\
**Post date:** [June 7, 2019, 1:46pm UTC](https://discourse.julialang.org/t/how-to-define-an-everywhere-defined-function-within-a-function/25044/2 "2019-06-07T13:46:17Z")

</div>

> [@dkarrasch](#):
>
> I want the `@eval` because I don’t want the `4σ` to be computed at every evaluation

Have you tried just doing this normally? There is fairly aggressive constant propagation these days.

---

<div class="post-metadata">

**Author:** ![dkarrasch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dkarrasch/32/7410_2.png) [@dkarrasch](https://discourse.julialang.org/u/dkarrasch)\
**Post date:** [June 7, 2019, 1:49pm UTC](https://discourse.julialang.org/t/how-to-define-an-everywhere-defined-function-within-a-function/25044/3 "2019-06-07T13:49:20Z")

</div>

I have tried with some of the `@code_` macros (most of which I don’t master very well, I should say), and it did seem to me like there was the `floatmul(%3, 4.0)` (or something like this in the code. But maybe I was doing it wrong?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [June 7, 2019, 2:10pm UTC](https://discourse.julialang.org/t/how-to-define-an-everywhere-defined-function-within-a-function/25044/4 "2019-06-07T14:10:45Z")

</div>

Have you benchmarked if this does anything to the runtime of the function? Since you have an exp call in there I would be surprised if it did.

---

<div class="post-metadata">

**Author:** ![dkarrasch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dkarrasch/32/7410_2.png) [@dkarrasch](https://discourse.julialang.org/u/dkarrasch)\
**Post date:** [June 7, 2019, 2:16pm UTC](https://discourse.julialang.org/t/how-to-define-an-everywhere-defined-function-within-a-function/25044/5 "2019-06-07T14:16:42Z")

</div>

Just did it.

```julia
julia> function gaussian(σ::Real=1.0)
           @eval function (x)
               exp(-abs2(x) / $(float(4σ)))
           end
       end
gaussian (generic function with 2 methods)

julia> using BenchmarkTools

julia> @benchmark $(gaussian(3.))(x) setup=(x = rand())
BenchmarkTools.Trial: 
  memory estimate: 0 bytes
  allocs estimate: 0
  --------------
  minimum time: 4.241 ns (0.00% GC)
  median time: 5.776 ns (0.00% GC)
  mean time: 6.128 ns (0.00% GC)
  maximum time: 66.726 ns (0.00% GC)
  --------------
  samples: 10000
  evals/sample: 1000

julia> function gaussian2(σ::Real=1.0)
           function (x)
               exp(-abs2(x) / float(4σ))
           end
       end
gaussian2 (generic function with 2 methods)

julia> @benchmark $(gaussian2(3.))(x) setup=(x = rand())
BenchmarkTools.Trial: 
  memory estimate: 0 bytes
  allocs estimate: 0
  --------------
  minimum time: 5.678 ns (0.00% GC)
  median time: 5.825 ns (0.00% GC)
  mean time: 6.194 ns (0.00% GC)
  maximum time: 64.749 ns (0.00% GC)
  --------------
  samples: 10000
  evals/sample: 1000

```

This will perhaps not be crucial in the overall process, but would be nice to avoid.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [June 7, 2019, 2:21pm UTC](https://discourse.julialang.org/t/how-to-define-an-everywhere-defined-function-within-a-function/25044/6 "2019-06-07T14:21:03Z")

</div>

Why do you need `@eval` for this? For example:

```julia
function gaussian(σ::Real=1.0)
    let s = -1/4σ
        x -> exp(s*abs2(x))
    end
end

```

(Though I’m skeptical that the 3% performance difference in your benchmark is worth a specialized higher-order function here.)

---

<div class="post-metadata">

**Author:** ![dkarrasch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dkarrasch/32/7410_2.png) [@dkarrasch](https://discourse.julialang.org/u/dkarrasch)\
**Post date:** [June 7, 2019, 2:33pm UTC](https://discourse.julialang.org/t/how-to-define-an-everywhere-defined-function-within-a-function/25044/7 "2019-06-07T14:33:47Z")

</div>

> [@stevengj](#):
>
> Why do you need `@eval` for this?

That was the only way I could come up with to avoid that (stupid) extra operation. I understand that this does not change the world, but it felt strange and I thought there should be a way to “precompute” this. Interestingly, when defined this way, there is no problem with `kernel = gaussian(3.)` being passed to different workers, **without** being `@everywhere`d. So, many thanks for your help!

---

<div class="post-metadata">

**Author:** ![affans](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/affans/32/11911_2.png) [@affans](https://discourse.julialang.org/u/affans)\
**Post date:** [June 7, 2019, 2:41pm UTC](https://discourse.julialang.org/t/how-to-define-an-everywhere-defined-function-within-a-function/25044/8 "2019-06-07T14:41:40Z")

</div>

Could someone explain the use of `@eval` here and what the OP was trying to achieve? Suppose the OP didn’t have trouble with the parallelism, how does the `@eval` work? If I do

```julia
kernel = gaussian(3.0)
kernel(0.2)

kernel2 = gaussian(4.0)
kernel2(0.2)

```

Wouldn’t that compute the `4\sigma` twice anyways?

---

<div class="post-metadata">

**Author:** ![dkarrasch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dkarrasch/32/7410_2.png) [@dkarrasch](https://discourse.julialang.org/u/dkarrasch)\
**Post date:** [June 7, 2019, 2:50pm UTC](https://discourse.julialang.org/t/how-to-define-an-everywhere-defined-function-within-a-function/25044/9 "2019-06-07T14:50:48Z")

</div>

> [@affans](#):
>
> Wouldn’t that compute the `4\sigma` twice anyways?

Yes, but the intention is to apply the same `kernel = gaussian(3.)` to many different arguments, i.e., `kernel(x)`, and precompute as much as possible that depends on `σ=3.0`.
