# Return tuple of user chosen functions, metaprogramming?

**URL:** https://discourse.julialang.org/t/return-tuple-of-user-chosen-functions-metaprogramming/19675
**Category:** General Usage
**Created:** [January 15, 2019, 8:26pm UTC](https://discourse.julialang.org/t/return-tuple-of-user-chosen-functions-metaprogramming/19675 "2019-01-15T20:26:30Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![MrUrq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrurq/32/8924_2.png) [@MrUrq](https://discourse.julialang.org/u/MrUrq)
#### Post date: [January 15, 2019, 8:26pm UTC](https://discourse.julialang.org/t/return-tuple-of-user-chosen-functions-metaprogramming/19675/1 "2019-01-15T20:26:30Z")

</div>

Hi,

I have a problem where, after som expensive calculations, an anonymous function is created. The anonymous function needs to return a tuple of the results depending on the users input. Here is an example of what I wish to achieve.

```julia
function run(funs::Array{Symbol,1})
    #f1,f2,f3 are expensive and only available at run time
    f1 = x->minimum(x)
    f2 = x->maximum(x)
    f3 = x->sum(x)
    
    return function (x)
        ...
    end
end

```

```julia
julia> foo = run([:f1, :f3])
julia> foo([1 2 3])
(6,1)

```

To me it seems like a problem which could (should?) be solved by metaprogramming; however, my attempts have been hacky at best. I’m sure there’s an elegant Julian way of doing it!

---

<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: [January 15, 2019, 8:43pm UTC](https://discourse.julialang.org/t/return-tuple-of-user-chosen-functions-metaprogramming/19675/2 "2019-01-15T20:43:27Z")

</div>

> [@MrUrq](#):
>
> function run(funs::Array{Symbol,1}) #f1,f2,f3 are expensive and only available at run time f1 = x-\>minimum(x) f2 = x-\>maximum(x) f3 = x-\>sum(x) return function (x) … end end

Something like this:

```julia

julia> function foo(funcs)

         return x -> [f(x) for f in funcs]

       end
foo (generic function with 2 methods)

julia> foo(funcs...) = foo(funcs)
foo (generic function with 2 methods)

julia> g = foo(f1, f2)
#9 (generic function with 1 method)

julia> g([3, 4, 5])
2-element Array{Int64,1}:
  5
 12

```

---

<div class="post-metadata">

### Author: ![simonbyrne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simonbyrne/32/19_2.png) [@simonbyrne](https://discourse.julialang.org/u/simonbyrne)
#### Post date: [January 15, 2019, 8:49pm UTC](https://discourse.julialang.org/t/return-tuple-of-user-chosen-functions-metaprogramming/19675/3 "2019-01-15T20:49:23Z")

</div>

Or if you want them to return a tuple:

```julia
julia> foo(funcs...) = x -> map(f -> f(x), funcs)
foo (generic function with 1 method)

julia> foo(sum, minimum, maximum)(rand(10))
(5.8259370715920795, 0.3263348387493512, 0.8915579235083304)

```

---

<div class="post-metadata">

### Author: ![MrUrq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrurq/32/8924_2.png) [@MrUrq](https://discourse.julialang.org/u/MrUrq)
#### Post date: [January 15, 2019, 9:20pm UTC](https://discourse.julialang.org/t/return-tuple-of-user-chosen-functions-metaprogramming/19675/4 "2019-01-15T21:20:02Z")

</div>

Thanks, returning a tuple is what I need!

Do you have an idea of how I could get the interface to work? The application where I’m using this is nested in an expensive function which generates `f1,f2,f3` in the example and both the number of functions and their order can vary based on the user input.

```julia
function run(funs::Array{Symbol,1})
    #f1,f2,f3 are expensive and only available at run time
    f1 = x->minimum(x)
    f2 = x->maximum(x)
    f3 = x->sum(x)
    
    return function (x)
        ...
    end
end

```

---

<div class="post-metadata">

### Author: ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)
#### Post date: [January 15, 2019, 9:35pm UTC](https://discourse.julialang.org/t/return-tuple-of-user-chosen-functions-metaprogramming/19675/5 "2019-01-15T21:35:15Z")

</div>

The following seems to work pretty well for the problem as you’ve posed it:

```julia
julia> function run(names::Vector{Symbol})
         library = Dict(
           :f1 => x -> minimum(x),
           :f2 => x -> maximum(x),
           :f3 => x -> sum(x)
         )
         functions_to_call = Tuple([library[s] for s in names])
         return function (x)
           call.(functions_to_call, Ref(x))
         end
       end
run (generic function with 1 method)

julia> call(f, x) = f(x)
call (generic function with 1 method)

julia> f = run([:f1, :f2])
#38 (generic function with 1 method)

julia> f([1,2,3])
(1, 3)

```

Some notes:

- I’m assembling a Dict mapping names to functions, rather than trying to look them up by the names of the variables they’re bound to. I wouldn’t recommend trying to access things inside some other function by their variable names: variable names don’t really exist in the compiled code, so looking things up by variable name isn’t a great idea.
- I construct a `Tuple` of functions to call instead of just a list so that Julia can correctly infer the number of outputs of the resulting function (a tuple’s length is part of its _type_, which is not true for an Array). That means that Julia can correctly infer the output type of `f()` in the above example:

```julia
julia> @code_warntype f([1,2,3])
Body::Tuple{Int64,Int64}
9 1 ─ %1 = %new(Base.RefValue{Array{Int64,1}}, x)::Base.RefValue{Array{Int64,1}} │╻╷╷ Type
  │ %2 = (Base.getfield)(%1, :x)::Array{Int64,1} ││╻╷╷╷╷╷╷╷╷╷ copy
  │ %3 = Base.identity::typeof(identity) │││╻╷╷╷╷╷ tuplebroadcast
  │ %4 = Base.min::typeof(min) ││││┃│││││││││ ntuple
  │ %5 = invoke Base._mapreduce(%3::typeof(identity), %4::typeof(min), $(QuoteNode(IndexLinear()))::IndexLinear, %2::Array{Int64,1})::Int64
  │ %6 = (Base.getfield)(%1, :x)::Array{Int64,1} ││││││╻╷╷╷╷╷ _broadcast_getindex
  │ %7 = Base.identity::typeof(identity) │││││││╻╷╷╷╷╷ _broadcast_getindex_evalf
  │ %8 = Base.max::typeof(max) ││││││││┃│││││ call
  │ %9 = invoke Base._mapreduce(%7::typeof(identity), %8::typeof(max), $(QuoteNode(IndexLinear()))::IndexLinear, %6::Array{Int64,1})::Int64
  │ %10 = (Core.tuple)(%5, %9)::Tuple{Int64,Int64} │││││            
  └── return %10   

```

and that in turn means that you should be able to use the resulting `f` efficiently:

```julia
julia> using BenchmarkTools

julia> @btime $f($([1,2,3]))
  7.089 ns (0 allocations: 0 bytes)
(1, 3)

```

---

<div class="post-metadata">

### Author: ![MrUrq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrurq/32/8924_2.png) [@MrUrq](https://discourse.julialang.org/u/MrUrq)
#### Post date: [January 15, 2019, 9:42pm UTC](https://discourse.julialang.org/t/return-tuple-of-user-chosen-functions-metaprogramming/19675/6 "2019-01-15T21:42:45Z")

</div>

Thanks for the help, this was precisely what I was looking for! Glad to see that it can be done with such good performance as well.
