# Obtaining a function's output type

**URL:** <https://discourse.julialang.org/t/obtaining-a-functions-output-type/11313>\
**Category:** General Usage\
**Tags:** question\
**Created:** [May 31, 2018, 10:51pm UTC](https://discourse.julialang.org/t/obtaining-a-functions-output-type/11313 "2018-05-31T22:51:18Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![jebej](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jebej/32/1784_2.png) [@jebej](https://discourse.julialang.org/u/jebej)\
**Post date:** [May 31, 2018, 10:51pm UTC](https://discourse.julialang.org/t/obtaining-a-functions-output-type/11313/1 "2018-05-31T22:51:18Z")

</div>

Given a function and some argument types, it should be possible to know the return type without actually running the executing the method. How can I do that? Is there something like a `functiontype(f,argtypes)`?

My goal is to be able to promote the type, given multiple functions and arguments as tuples, e.g. as

```julia
promote_type(functiontype.((cis,cos),(Float32,Float64))...) = Complex{Float64}

```

Thanks,  
Jeremy

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [June 1, 2018, 12:04am UTC](https://discourse.julialang.org/t/obtaining-a-functions-output-type/11313/2 "2018-06-01T00:04:17Z")

</div>

In 0.6, you might want

```julia
julia> Base.return_types(cos, Tuple{Float64})
1-element Array{Any,1}:
 Float64

```

edit: Note that this is afaik intended for use in `@generated` functions, and not terribly fast for runtime use.

---

<div class="post-metadata">

**Author:** ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)\
**Post date:** [June 1, 2018, 1:05am UTC](https://discourse.julialang.org/t/obtaining-a-functions-output-type/11313/3 "2018-06-01T01:05:38Z")

</div>

No it cannot be used in generated functions. It’s also not intended for use in what the OP wants. It’s there only for empty comprehensions.

---

<div class="post-metadata">

**Author:** ![jebej](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jebej/32/1784_2.png) [@jebej](https://discourse.julialang.org/u/jebej)\
**Post date:** [June 1, 2018, 4:50pm UTC](https://discourse.julialang.org/t/obtaining-a-functions-output-type/11313/4 "2018-06-01T16:50:09Z")

</div>

What would be the recommended way of getting the type of a function’s output then?

I am trying to allocate an array, and since values from those functions will get added up in there, I need to allocate the correct type to begin with.

---

<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 1, 2018, 5:45pm UTC](https://discourse.julialang.org/t/obtaining-a-functions-output-type/11313/5 "2018-06-01T17:45:14Z")

</div>

> [@jebej](#):
>
> I am trying to allocate an array, and since values from those functions will get added up in there, I need to allocate the correct type to begin with.

If you can, use something like `map` or a generator/comprehension or `broadcast` (or a dot call), since those functions will take care of this for you.

The way `map` works, if I recall, is:

1. If the collection is non-empty, evaluate the first element `x`, and speculatively allocate an array of `T = typeof(x)`.

2. Loop over the remaining elements. As each element `y` is computed, if it is of type `T`, then store it in the existing array. Otherwise, set `S = typejoin(T, typeof(y))`, allocate a new array of type `S`, and copy the old elements along with `y` to this new array. Discard the old array and continue with `T = S`.

3. If the collection was empty (so that there is no first element), return an empty array whose type is computed by `Core.Inference.return_type`

Basically, this is optimized for type-stable, inferrable functions (the only case that will generally be fast), but still works for type-unstable functions.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [June 1, 2018, 6:33pm UTC](https://discourse.julialang.org/t/obtaining-a-functions-output-type/11313/6 "2018-06-01T18:33:36Z")

</div>

Hah, we have the same thread going on over in #dev: [Promote\_op and preallocating result of linear operators - #4 by mbauman](https://discourse.julialang.org/t/promote-op-and-preallocating-result-of-linear-operators/11332/4)

---

<div class="post-metadata">

**Author:** ![jebej](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jebej/32/1784_2.png) [@jebej](https://discourse.julialang.org/u/jebej)\
**Post date:** [June 1, 2018, 9:39pm UTC](https://discourse.julialang.org/t/obtaining-a-functions-output-type/11313/7 "2018-06-01T21:39:55Z")

</div>

I’m confused as to why this is complicated: isn’t the return typed determined by inference at compile time? Assuming that the function is type-stable of course…

---

<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:** [June 1, 2018, 9:53pm UTC](https://discourse.julialang.org/t/obtaining-a-functions-output-type/11313/8 "2018-06-01T21:53:47Z")

</div>

The reason is that inference isn’t part of the language, it’s part of the implementation. Consequently, as the implementation improves, it may also improve inference, changing the results.

For example, suppose that you have a method which returns `Union{Int64, Nothing}`, but then version 1.1 of Julia adds a new compiler pass which is able to determine that `nothing` is never returned. This would change the output of `return_types` to be just `Int64`. Or suppose you have a Julia interpreter mode, which simply assumes that `return_types` is always `Any` (disclaimer: I have no idea if this is what the interpreter actually does).

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [June 1, 2018, 9:59pm UTC](https://discourse.julialang.org/t/obtaining-a-functions-output-type/11313/9 "2018-06-01T21:59:14Z")

</div>

> [@jebej](#):
>
> Assuming that the function is type-stable of course

That’s precisely the rub. Not only could inference be disabled, but collecting things like:

```julia
f() = rand() > 1 ? 1 : 1.0
[f() for _ in 1:3]

```

used to return an `Vector{Any}` (a long long time ago). We’ve made inference better, so now it’d be a `Vector{Union{...}}` if we still relied on inference, but that’s precisely the problem — ideally inference improvements wouldn’t change behaviors. At the end of the day, it’s an optimization.
