Type-inferable interleave two tuples

I am working through the 18.S096 course. In lecture 3, an exercise is

Write a type-inferable function to… interleave the elements of two tuples

Is this an OK solution?

_il(bs,a,arest...) = (a,_il(arest,bs...)...)
_il(bs) = () # terminate when we run out of elements for one sequence
interleave(as,bs) = _il(bs,as...)

interleave((1,2,3), (4,5,6))

@code_typed interleave((1,2,3), (4,5,6)) gives

LambdaInfo for interleave(::Tuple{Int64,Int64,Int64}, ::Tuple{Int64,Int64,Int64})
        SSAValue(4) = (Core.getfield)(as,2)::Int64
        SSAValue(5) = (Core.getfield)(as,3)::Int64
        # meta: location In[10] _il 1
        SSAValue(2) = (Core.getfield)(bs,2)::Int64
        SSAValue(3) = (Core.getfield)(bs,3)::Int64
        # meta: pop location
        return (Core.tuple)((Core.getfield)(as,1)::Int64,(Core.getfield)(bs,1)::Int64,SSAValue(4),SSAValue(2),SSAValue(5),SSAValue(3))::Tuple{Int64,Int64,Int64,Int64,Int64,Int64}

but I am still learning how to read that, so I am unsure.

The output has been inferred fully, so that is good. One tip is to use @code_warntype which is a colored version of @code_typed and watch out for red.

The other thing to do when testing type stability with tuples is to fill the slots with different types like (1, 2.0, true, "a"). This ensures that inference understands the order that the tuples are put together. If they are all Int64 and the compiler can infer the length is 6, then it will appear type stable even if the general case isn’t.

1 Like