# How to resolve \`Any\`s in this function?

**URL:** <https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717>\
**Category:** Performance\
**Created:** [March 8, 2021, 8:49am UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717 "2021-03-08T08:49:57Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![amrods](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/amrods/32/2543_2.png) [@amrods](https://discourse.julialang.org/u/amrods)\
**Post date:** [March 8, 2021, 8:49am UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717/1 "2021-03-08T08:49:57Z")

</div>

Consider this:

```julia
using ComponentArrays, Parameters

function test(g, a; data=data)
    @unpack P = data

    if g == 1
        oc = (g, a) -> P[g, a]
    elseif g == 2
        oc = (g, a) -> P[g, a] + 1
    end
    return oc(g, a)
end

const testca = ComponentArray{Float64}(P = [1 2; 3 4])

```

How can I get rid of those `Any`s in the following?

```julia
@code_warntype test(1, 2; data = testca)
Variables
  #unused#::Core.Compiler.Const(var"#test##kw"(), false)
  @_2::NamedTuple{(:data,),Tuple{ComponentVector{Float64}}}
  @_3::Core.Compiler.Const(test, false)
  g::Int64
  a::Int64
  data::ComponentVector{Float64}
  @_7::ComponentVector{Float64}

Body::Any
1 ─ %1 = Base.haskey(@_2, :data)::Core.Compiler.Const(true, false)
│ %1
│ (@_7 = Base.getindex(@_2, :data))
└── goto #3
2 ─ Core.Compiler.Const(:(@_7 = Main.data), false)
3 ┄ %6 = @_7::ComponentVector{Float64}
│ (data = %6)
│ %8 = (:data,)::Core.Compiler.Const((:data,), false)
│ %9 = Core.apply_type(Core.NamedTuple, %8)::Core.Compiler.Const(NamedTuple{(:data,),T} where T<:Tuple, false)
│ %10 = Base.structdiff(@_2, %9)::Core.Compiler.Const(NamedTuple(), false)
│ %11 = Base.pairs(%10)::Core.Compiler.Const(Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}(), false)
│ %12 = Base.isempty(%11)::Core.Compiler.Const(true, false)
│ %12
└── goto #5
4 ─ Core.Compiler.Const(:(Base.kwerr(@_2, @_3, g, a)), false)
5 ┄ %16 = Main.:(var"#test#5")(data, @_3, g, a)::Any
└── return %16

```

---

<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:** [March 8, 2021, 8:57am UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717/2 "2021-03-08T08:57:42Z")

</div>

Just as a note, on the upcoming 1.6 (you can try the RC from the julia download page) this infers correctly:

```julia
julia> @code_warntype test(1, 2; data = testca)
Variables
  #unused#::Core.Const(var"#test##kw"())
  @_2::NamedTuple{(:data,), Tuple{ComponentVector{Float64}}}
  @_3::Core.Const(test)
  g::Int64
  a::Int64
  data::ComponentVector{Float64}
  @_7::ComponentVector{Float64}

Body::Float64

```

---

<div class="post-metadata">

**Author:** ![amrods](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/amrods/32/2543_2.png) [@amrods](https://discourse.julialang.org/u/amrods)\
**Post date:** [March 8, 2021, 10:56am UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717/3 "2021-03-08T10:56:22Z")

</div>

any word on when it will be released?

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [March 8, 2021, 11:05am UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717/4 "2021-03-08T11:05:52Z")

</div>

I don’t know how this example generalizes but maybe you could try something like a manual return type declaration:

```julia
function test(g, a; data=data)::eltype(data)

```

---

<div class="post-metadata">

**Author:** ![amrods](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/amrods/32/2543_2.png) [@amrods](https://discourse.julialang.org/u/amrods)\
**Post date:** [March 8, 2021, 11:14am UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717/5 "2021-03-08T11:14:09Z")

</div>

That works. I’m wondering if `eltype(data)` is evaluated at the time I define the function, or it acts as a regular argument to `test`. That is, for every possible type of `data`, that annotation yields the correct `eltype`?

---

<div class="post-metadata">

**Author:** ![GunnarFarneback](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gunnarfarneback/32/1827_2.png) [@GunnarFarneback](https://discourse.julialang.org/u/GunnarFarneback)\
**Post date:** [March 8, 2021, 11:34am UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717/6 "2021-03-08T11:34:09Z")

</div>

To be honest I was surprised that it was valid at all and it doesn’t seem to generalize greatly when I test it, so I have to pass on that question.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [March 8, 2021, 12:43pm UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717/7 "2021-03-08T12:43:34Z")

</div>

While we wait for 1.6, this works and is at least general for the type of element of `data`:

```julia
julia> function test(g, a; data::ComponentArray{T}=data) where T
           @unpack P = data

           if g == 1
               oc = (g, a) -> P[g, a]
           elseif g == 2
               oc = (g, a) -> P[g, a] + 1
           end
           return oc(g, a)::T
       end

```

That is somewhat similar to what was proposed above, except that the function could return something different from `eltype(data)` if some other computation is performed afterwards with the result of `oc(g,a)`.

---

<div class="post-metadata">

**Author:** ![amrods](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/amrods/32/2543_2.png) [@amrods](https://discourse.julialang.org/u/amrods)\
**Post date:** [March 8, 2021, 11:11pm UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717/9 "2021-03-08T23:11:00Z")

</div>

How can I annotate `oc` inside the `if ... end`? or more generally, how can I annotate the return value of an anonymous function?  
The reason I am asking is that in my real example I have to do some arithmetic on `oc` before returning.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [March 9, 2021, 12:19am UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717/10 "2021-03-09T00:19:39Z")

</div>

> [@amrods](#):
>
> I have to do some arithmetic on `oc`

I am not sure if I understand you here, because that would literally mean peform arithmetic on a function. But there you can do, for example:

```julia
oc_result = oc(g,a)::T

# do whatever you want with oc_result

return ...

```

Also maybe you should consider if you really need an anonymous function there, or a simple function that returns what you want:

```julia
julia> function oc(g,a,P)
         if g == 1
           return P[g,a]
         else
           return (P[g,a] + 1)
         end
       end

       function test(g, a; data=data)
           @unpack P = data
           oc_result = oc(g,a,P)
           return oc_result
       end

```

If that is possible, it is also simpler and safer, no need to annotate any type anywhere.

---

<div class="post-metadata">

**Author:** ![amrods](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/amrods/32/2543_2.png) [@amrods](https://discourse.julialang.org/u/amrods)\
**Post date:** [March 9, 2021, 4:14am UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717/11 "2021-03-09T04:14:08Z")

</div>

In my application, if I separate the functions like that I get a return type `Union{Nothing, Float64}` (in Julia 1.6 rc1). I got around it by slightly modifying `oc`:

```julia
function oc(g,a,P)
    if g == 1
        ret = P[g,a]
    else if g == 2
        ret = P[g,a] + 1
    end
    return ret
end

```

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [March 9, 2021, 10:35am UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717/12 "2021-03-09T10:35:00Z")

</div>

The reason you get `Union` for this:

```julia
function oc(g,a,P)
    if g == 1
        ret = P[g,a]
    elseif g == 2
        ret = P[g,a] + 1
    end
    return ret
end

```

is quite simple: what should `ret` be, if `g` is neither `1` nor `2`? The compiler doesn’t pull a value out of thin air, and since no value was specified, that case is inferred as `Nothing`. Together with the other branches, the complete return type becomes `Union{Nothing, Int}`, to signal that the returned value is either an `Int` or `nothing`.

---

<div class="post-metadata">

**Author:** ![amrods](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/amrods/32/2543_2.png) [@amrods](https://discourse.julialang.org/u/amrods)\
**Post date:** [March 9, 2021, 10:39am UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717/13 "2021-03-09T10:39:58Z")

</div>

I get `Union` for @lmiq ’s proposal. I get `Float64` for my modification with `ret`.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [March 9, 2021, 10:59am UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717/14 "2021-03-09T10:59:47Z")

</div>

Actually no, I removed the `g==2` from the `else` branch because of that. But you would in the original form of the function.

---

<div class="post-metadata">

**Author:** ![amrods](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/amrods/32/2543_2.png) [@amrods](https://discourse.julialang.org/u/amrods)\
**Post date:** [March 9, 2021, 11:06am UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717/15 "2021-03-09T11:06:15Z")

</div>

My bad, I misread your example. Do you think there is any penalty for my case? I am also realising that I didn’t exactly copy what I had in my code (the `elseif`). Now fixed.

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [March 9, 2021, 11:06am UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717/16 "2021-03-09T11:06:30Z")

</div>

Right - if you use a plain `else` instead of `elseif g == 2`, the `else` branch catches all other possible cases, so the final `ret` always hits either the `if` or the `else` branch and is thus defined.

---

<div class="post-metadata">

**Author:** ![amrods](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/amrods/32/2543_2.png) [@amrods](https://discourse.julialang.org/u/amrods)\
**Post date:** [March 9, 2021, 11:10am UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717/17 "2021-03-09T11:10:57Z")

</div>

Still I can get around the other cases (my example with `elseif`) with `ret` no? I remember back in Julia 0.4, I used to often use that construct.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [March 9, 2021, 12:44pm UTC](https://discourse.julialang.org/t/how-to-resolve-any-s-in-this-function/56717/18 "2021-03-09T12:44:07Z")

</div>

> [@amrods](#):
>
> Still I can get around the other cases (my example with `elseif` ) with `ret` no?

The compiler is figuring out there that `ret` is always an integer and the function is being correctly inferred. But note that that is somewhat unpredictable, for example it will return an error if `g` is not `1` nor `2`:

```julia
julia> oc(0,2,[1 2 3 ; 1 2 3])
ERROR: UndefVarError: ret not defined

```

Probably it is not a good idea to rely on that behavior. If `g` can only be 1 or 2, it is better to add an error message specific for that,

```julia
g != 1 && g != 2 && error("g is neither 1 or 2")

```

or

```julia
@assert g == 2

```

Otherwise set a default value for `g` somewhere.
