Why doesn't empty array match any type signature for array?

function foo(x::Tuple{Array{Float64,2}, String, Bool})
    a, s, b = x
    if a != []
        println(a)
    end
end

function main()
    foo(([], "", false))
end

main()

ERROR: LoadError: MethodError: no method matching foo(::Tuple{Array{Any,1},String,Bool})

I’ll just type annotate the empty array…

function main()
    foo(([]::Array{Float64,2}, "", false))
end

ERROR: LoadError: TypeError: in typeassert, expected Array{Float64,2}, got Array{Any,1}

I get this problem a lot…
Strangely i always want to solve it my annotating the type in the caller like I’ve done, and everytime i do that i remember that i can’t do that. it’s seems very natural, am i getting Julia mixed up with another language ? :laughing:
I eventually solve it by removing the declaration, but I’m not going to do that any more. Some kind soul on the Julia forum is going to show me the error in my ways :slight_smile:

First, this specificity of types of the function parameters is probably not needed.

But if you insist, the error is quite clear:
[] is not of type Array{Float64,2} so it doesn’t match.
What you need is a Array{Float64,2}, e.g.:

foo( (Array{Float64,2}([[] []]), "", false))
2 Likes

A proper array constructor would be:
Array{Float64}(undef,0,2)

I would suggest:

foo((Float64[[] []], "", false))

Unless you actually want an array of arrays.

The typessert does not work as you think it works. It will try to convert and throw an exception if it is wrong, and if used in a binding (not a literal) it will force that binding to only accept values of that type. It will not, however, serve to define which is the element type of the array literal. In such case, you declare the array as Type[...] for an array of type Type and contents ....

1 Like

Alternatively:

julia> function foo(x::Tuple{AbstractArray, String, Bool})
           a, s, b = x
           if a != []
               println(a)
           end
       end

julia> foo(([], "", false))

1 Like

Yes, widening signatures like that is almost always the best answer. Not only will that work with [], it’ll also make your function just work for things like Diagonals, static arrays, sparse matrices, etc., etc.

2 Likes

not needed, but desirable. they this came up when I tried to pass an Array{Float64,1} instead of Array{Float64,2} and spent the next 5 minutes trying to figure out why i was getting an error message…

also,

x=Array{Float64}(undef,0,2)
x==[]
false

Check isempty instead of comparing to an empty vector.

2 Likes

Yes, sometimes. I tend in a current project to the same because making the types explicit helps me to recognize what the function has to do somehow. The speaking name together with the parameter types does help me to be more productive.

function main()
    foo((Array{Float64,2}[], "", false))
end
ERROR: LoadError: MethodError: no method matching foo(::Tuple{Array{Array{Float64,2},1},String,Bool})

Yes, I was wrong about the notation, the [[] []] is actually needed, but the correct form is typeof((Float64[[] []], "", false)) not the one presented by @oheil, I will edit the original.

julia> typeof((Float64[[][]], "", false))
ERROR: BoundsError: attempt to access 0-element Array{Any,1} at index []
Stacktrace:
 [1] throw_boundserror(::Array{Any,1}, ::Tuple{}) at .\abstractarray.jl:537
 [2] checkbounds at .\abstractarray.jl:502 [inlined]
 [3] _getindex at .\abstractarray.jl:1002 [inlined]
 [4] getindex(::Array{Any,1}) at .\abstractarray.jl:980
 [5] top-level scope at REPL[1]:1

I cannot reproduce this last error, in Julia 1.4.2 I have:

julia> typeof((Float64[[] []], "", false))
Tuple{Array{Float64,2},String,Bool}
 

OH! if you look very carefully at my example you’ll see that i’m missing a space !!
so tricksy…

my bad, thank you for your solution :slight_smile:

haha. in looking at your original reply , the line split right between the two ‘[ ]’ elements. lol. that’s why i didn’t realize there was a space there. Good to know that the space is significant.

Oh, yes, spacing is significant in Julia (while not so much like Python indentation). I recommend always copying an entire block of code, instead of copying until the end of the line, and then the rest, to avoid such problems.