Why are returned types different in comprehension over an empty range if called from a function vs top level?

jishnub
Tue, 05 Sep 2023 07:02:26 +0000
General Usage

julia> using ApproxFun

julia> rs = Jacobi(5,4);

julia> d = domain(rs);

julia> Sf = JacobiWeight(0,2,ConstantSpace(d));

julia> using ApproxFun.ApproxFunSingularities: jacobiweight

julia> using ApproxFun.ApproxFunBase: ConcreteMultiplication

julia> min(rs.b, Sf.β)-1:-1:1 # empty range
-1:-1:0

julia> [ConcreteMultiplication(jacobiweight(1,0,d), Jacobi(rs.b-i,rs.a,d)) for i in min(rs.b, Sf.β)-1:-1:1]
Any[]

julia> ((rs,Sf,d) -> [ConcreteMultiplication(jacobiweight(1,0,d), Jacobi(rs.b-i,rs.a,d)) for i in min(rs.b, Sf.β)-1:-1:1])(rs,Sf,d)
ConcreteMultiplication{JacobiWeight{ConstantSpace{ChebyshevInterval{Float64}, Float64}, ChebyshevInterval{Float64}, Float64, Int64}, Jacobi{ChebyshevInterval{Float64}, Float64, Int64}, Float64}[]

julia> VERSION
v"1.9.3"

Why are the types different? The second call is identical to the first, except this time this is placed in a function. My impression was that this might help with type-inference, but won’t change the actual types that are returned.

Edit: On second thought, perhaps the inferred type (using @default_eltype) is used to allocate the container, which is a bit unfortunate

julia> G =(ConcreteMultiplication(jacobiweight(1,0,d), Jacobi(rs.b-i,rs.a,d)) for i in min(rs.b, Sf.β)-1:-1:1)
Base.Generator{StepRange{Int64, Int64}, var"#15#16"}(var"#15#16"(), -1:-1:0)

julia> Base.@default_eltype(G)
Any

julia> ((rs,Sf,d) -> (G = (ConcreteMultiplication(jacobiweight(1,0,d), Jacobi(rs.b-i,rs.a,d)) for i in min(rs.b, Sf.β)-1:-1:1); Base.@default_eltype(G)))(rs,Sf,d)
ConcreteMultiplication{JacobiWeight{ConstantSpace{ChebyshevInterval{Float64}, Float64}, ChebyshevInterval{Float64}, Float64, Int64}, Jacobi{ChebyshevInterval{Float64}, Float64, Int64}, Float64}

4 posts - 2 participants