# Define data-dependent function, various ways

**URL:** <https://discourse.julialang.org/t/define-data-dependent-function-various-ways/48988>\
**Category:** New to Julia\
**Tags:** closure, functors\
**Created:** [October 25, 2020, 6:15pm UTC](https://discourse.julialang.org/t/define-data-dependent-function-various-ways/48988 "2020-10-25T18:15:58Z")\
**Posts on this page:** 1\
**Showing post:** 4

<div class="post-metadata">

**Author:** ![ffevotte](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ffevotte/32/6587_2.png) [@ffevotte](https://discourse.julialang.org/u/ffevotte)\
**Post date:** [October 25, 2020, 9:27pm UTC](https://discourse.julialang.org/t/define-data-dependent-function-various-ways/48988/4 "2020-10-25T21:27:27Z")

</div>

I think [function-like objects](https://docs.julialang.org/en/v1/manual/methods/#Function-like-objects) (sometimes called “functors”) would be yet another option to achieve the same kind of things.

(AFAIU, this is what’s internally used to implement closures, and I think it requires a bit less work for the compiler to optimize. Maybe someone more knowledgeable will chime in and confirm or correct this)

```julia
struct Fun
    data :: Vector{Int}
end

function (f::Fun)(x)
  s = 0.
  for i in 1:length(x)
    s += (x[i]-f.data[i])^2
  end
  s
end

println(" Functor: ")
functor = Fun(0:100)
f5 = @btime solver($functor, $x0)

```

On my system, the single call benchmark yields:

```julia
 Global, non-constant data: 
  8.206 μs (404 allocations: 6.31 KiB)
 Global, constant data: 
  155.388 ns (0 allocations: 0 bytes)
 Closure: 
  138.079 ns (0 allocations: 0 bytes)
 Let block: 
  188.767 ns (0 allocations: 0 bytes)
 Functor: 
  155.384 ns (0 allocations: 0 bytes)

```

and the multiple-call benchmark:

```julia
 Global const data:
  18.120 μs (200 allocations: 3.13 KiB)
 Closure:
  18.159 μs (201 allocations: 3.14 KiB)
 Let block:
  19.642 μs (200 allocations: 3.13 KiB)
 Functor:
  13.994 μs (0 allocations: 0 bytes)

```

  

* * *

> **Complete code, benchmarking all variants so far**
>
> ```julia
> using BenchmarkTools
> using Test
> 
> # The "solver"
> 
> function solver(f,x0)
> f(x0)
> end
> 
> # The "data", declared or not as constant
> 
> data = collect(0:100)
> const data_const = collect(0:100)
> 
> # The "initial point"
> 
> x0 = ones(length(data))
> 
> #
> # using global, non-constant, data (wrong way)
> #
> 
> function f_global_non_const_data(x)
> s = 0.
> for i in 1:length(x)
> s += (x[i]-data[i])^2
> end
> s
> end
> println(" Global, non-constant data: ")
> f1 = @btime solver($f_global_non_const_data,$x0)
> 
> #
> # Using constant global data
> #
> function f_global_const_data(x)
> s = 0.
> for i in 1:length(x)
> s += (x[i]-data_const[i])^2
> end
> s
> end
> println(" Global, constant data: ")
> f2 = @btime solver($f_global_const_data,$x0)
> 
> #
> # Using a closure (pass non-const data)
> #
> function f_closure(x,data)
> s = 0.
> for i in 1:length(x)
> s += (x[i]-data[i])^2
> end
> s
> end
> println(" Closure: ")
> f3 = @btime solver(x -> f_closure(x,$data),$x0)
> 
> #
> # Using a let block
> #
> let
> let_data = collect(0:100)
> function f_let(x,let_data)
> s = 0.
> for i in 1:length(x)
> s += (x[i]-let_data[i])^2
> end
> s
> end
> global f_let(x) = f_let(x,let_data)
> end
> println(" Let block: ")
> f4 = @btime solver($f_let,$x0)
> 
> struct Fun
> data :: Vector{Int}
> end
> 
> function (f::Fun)(x)
> s = 0.
> for i in 1:length(x)
> s += (x[i]-f.data[i])^2
> end
> s
> end
> 
> println(" Functor: ")
> functor = Fun(0:100)
> f5 = @btime solver($functor, $x0)
> 
> @test f1 ≈ f2 ≈ f3 ≈ f4 ≈ f5
> 
> # Multiple calls:
> 
> function call_solver(f,x0)
> s = 0.
> for i in 1:100
> s += solver(f,x0)
> end
> s
> end
> 
> println("Multiple calls:")
> 
> println(" Global const data:")
> @btime call_solver($f_global_const_data,$x0)
> println(" Closure:")
> @btime call_solver(x -> f_closure(x,$data),$x0)
> println(" Let block:")
> @btime call_solver($f_let,$x0)
> println(" Functor:")
> @btime call_solver($functor,$x0)
> 
> ```

---

_[View the full topic](https://discourse.julialang.org/t/define-data-dependent-function-various-ways/48988)._
