# Create a struct with uninitialized fields

Having a mutable struct, e.g.:

``````mutable struct Point
x
y
end
``````

is it possible to construct its instance with uninitialized fields and set them later? E.g.:

``````p = create_uninitialized(Point)    # <-- anything like this?
p.x = 10.0
p.y =  20.0
``````

Note: we can do it with arrays, e.g. `Array{Float64,1}(10)`.

Alternatively, I’d be happy to hear about `similar()` for structs, i.e. a function that takes an instance of a struct and creates similar instance with dummy field values:

``````p = Point(8.0, 11.0)
p2 = similar_struct(p)    # <-- like this
p2.x = 10.0
p2.y = 20.0
``````

Currently I use:

``````p = Point(8.0, 10.0)
p2 = deepcopy(p)
p2.x = 10.0
p2.y = 20.0
``````

But `deepcopy` is expensive and doesn’t work for all types.

2 Likes

Like this?

``````julia> mutable struct Point
x
y
Point() = new()
end

julia> p = Point()
Point(#undef, #undef)

julia> p.x = 2
2

julia> p.y = 3
3

julia> p
Point(2, 3)
``````

Or do you want to do it without having access to the inner constructor?

12 Likes

Yes, without any restrictions on a target type. I.e. user of this function should be able to use it for any mutable struct.

(However, thanks for the interesting trick - I didn’t know inner constructors may be used like this).

1 Like

What if I want to do this when I don’t have access to the inner constructor? Using Core is fine; the context here is I am trying to refactor a codebase that uses `ccall` to internal functions to be less fragile. So using Base functions would be best, but Core is still an improvement.

I ended up with the following implementation:

``````"""
__new__(T, args...)
User-level version of the `new()` pseudofunction.
Can be used to construct most Julia types, including structs
without default constructors, closures, etc.
"""
@generated function __new__(T, args...)
return Expr(:splatnew, :T, :args)
end
``````

I did’t try it with `undef` initializer, but given actual arguments, it works pretty well for quite a wide range if use cases in Ghost.jl. One caution though is that since `:new`/`:splatnew` are quite low-level, Julia won’t validate this expression, so misuse may lead to segfault.

4 Likes