TypeError for setfield! using Unions

#1

I am trying to set a field of a mutable composite type that happens to be an array of type Union{Float64,Nothing}, but am unable to do this successfully, and would like to understand why. As a MWE, I have

mutable struct TestFunction
    x::Union{Float64, Nothing}
    y::Array{Union{Float64, Nothing},1}
    function TestFunction(a::String, b::Float64)
        println("Hello, world!: $a $b")
        return new(nothing, [nothing])
    end
end

testStruct = TestFunction("hello", 3.0)
testVar = collect(0:0.1:2)
setfield!(testStruct, :y, testVar)

When I run this code, I get the following error at the last line:

ERROR: TypeError: in setfield!, expected Array{Union{Nothing, Float64},1}, got Array{Float64,1}

However, if I instead do

testStruct.y = testVar

it works just fine. It seems like both of these should work, but I don’t quite understand why the former doesn’t. Any help would be much appreciated.

0 Likes

#2
0 Likes

#3

Thanks - I see how the automatic conversion doesn’t happen, and that convert should take care of it. I tried modifying the last line so that it now reads

setfield!(testStruct, :y, convert(fieldtype(testStruct, :y), testVar))

This now produces a new, improved error:

ERROR: TypeError: in fieldtype, expected DataType, got TestFunction

I think that this is because I am using an inner constructor function. I can’t seem to get the type of the struct - suggestions?

0 Likes

#4

Ah, I got it. I needed to pass in the type of testStruct, so the last line needed to be

setfield!(testStruct, :y, convert(fieldtype(typeof(testStruct), :y), testVar))

Thanks again for your help.

0 Likes