How to assert type after if-else


#1

Suppose my code looks like this:

    if condition
        x = complicated_expression
        y = another_complicated_expression
    else
        x = a_third_complicated_expression
        y = a fourth_complicated_expression
    end

Suppose I know that x has type T and y has type U after this if-else block, but I suspect that the compiler may not be able to determine this. Therefore, I want to assert the types of x and y after then if-else block so that subsequent code that uses these variables can be properly specialized. What is the correct, idiomatic and performant way to make such an assertion? For example, what about

    x = x::T 
    y = y::U

at the end of the block? Do I actually need an assignment statement, or is the statement x::T a valid type assertion? Or is it better to put a declaration before the block?


#2

The pattern you’ve shown,

x = x::T
y = y::U

is actually used in a number of places in Base. One random example is in inference. Thus I think it’s reasonable to use that pattern in your own code. At least if it’s good enough for the folks who write the type inference code, it’s good enough for me. :slight_smile:


#3

I don’t think the assignment is needed in x = x::T as the part x::T is a type assertion and will throw an error. So there is no point in re-assining x to x. Have a look at the documentation https://docs.julialang.org/en/stable/manual/types/#Type-Declarations-1.

Alternatively, you can use a convert declaration local x::T which will work irrespective of where in the scope block it is. Both should help the compiler equally but have slightly different semantics.


#4

x::T do not have the same parsing on 0.5.


#5

One possible way to do it would be

if condition
    x = complicated_expression::T
    y = another_complicated_expression::U
else
    x = a_third_complicated_expression::T
    y = a fourth_complicated_expression::U
end

But you would need to be in a hard local scope to use x::T


#6

What about

x = (condition ? complicated_expression : another_complicated_expression)::T
y = (condition ? a_third_complicated_expression :
     a_fourth_complicated_expression)::U

If the compiler had difficulties with x and this is the only thing that prevents inference in y, you may be able to omit the ::U.