# ConstructFrom.jl - Construct objects without spelling out their types

**URL:** <https://discourse.julialang.org/t/constructfrom-jl-construct-objects-without-spelling-out-their-types/97459>\
**Category:** General Usage\
**Tags:** constructors\
**Created:** [April 14, 2023, 8:25am UTC](https://discourse.julialang.org/t/constructfrom-jl-construct-objects-without-spelling-out-their-types/97459 "2023-04-14T08:25:34Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![ettersi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ettersi/32/6829_2.png) [@ettersi](https://discourse.julialang.org/u/ettersi)\
**Post date:** [April 14, 2023, 8:25am UTC](https://discourse.julialang.org/t/constructfrom-jl-construct-objects-without-spelling-out-their-types/97459/1 "2023-04-14T08:25:34Z")

</div>

Over the past couple of weeks, I’ve frequently had to write code like the following.

```julia
struct MyType
    data::Dict{Int, Dict{Float64, String}}
end

MyType() = MyType(Dict{Int, Dict{Float64, String}}()) 
                 #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

function Base.insert!(m::MyType, i, x, s)
    get!(m.data, i, Dict{Float64, String}())[x] = s
                   #^^^^^^^^^^^^^^^^^^^^^
end

```

The issue here is that at the highlighted places, I have to repeat either parts or all of the type of `data` without providing any meaningful additional information. This seems unnecessarily tedious to write, read, and maintain.

Fortunately, there is an easy way to avoid this: Julia inserts an implicit `convert()` in many places, so if we define a `Default` type which “converts” itself to any type `T` simply by constructing a new `T()`, then instead of repeating the long and complicated types we can simply write `Default()` in the places marked above.

I’ve trialed a slightly more general version of this `Default` type in the [ConstructFrom.jl package](https://github.com/ettersi/ConstructFrom.jl), and so far I’ve been quite happy with the result. The one additional twist introduced by ConstructFrom.jl is that instead of restricting ourselves to constructors of the form `T()`, it allows the user to pass arguments which are then forwarded to the constructor of `T`. For example:

```julia
julia> vec::Vector{Vector{Int}} = construct_from(undef, 3);

julia> vec
3-element Vector{Vector{Int64}}:
 #undef
 #undef
 #undef

```

I’m now playing with the thought of registering my package on the Julia registry, but before doing so I thought I’d first ask for some input here. In particular, I’m quite surprised that a package like this doesn’t seem to exist already (it tackles a fairly common problem, it has a very simple solution (6 lines of relevant code), and it has a precedent in the form of [Rust’s `Default` trait](https://doc.rust-lang.org/std/default/trait.Default.html)). Is this issue already addressed by some other language feature or package, or is there some fundamental problem with my solution that I have not discovered yet?

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [April 14, 2023, 9:59am UTC](https://discourse.julialang.org/t/constructfrom-jl-construct-objects-without-spelling-out-their-types/97459/2 "2023-04-14T09:59:06Z")

</div>

Interesting approach! This kind of code duplication (types) happens from time to time, but not that often – probably that’s why there was no similar package before.

Some unintuitive and potentially confusing behavior, in addition to limitations from README:

```julia
julia> b = a::Dict = construct_from();
julia> a
Dict{Any, Any}()
# b remains construct_from()
julia> b
construct_from()

# works:
julia> c::Dict{Int} = Dict{Int,Any}()
Dict{Int64, Any}()
# doesn't:
julia> d::Dict{Int} = construct_from()
ERROR: MethodError: no method matching (Dict{Int64})()

```

Not a fault of your package, that’s just how Julia works.

---

<div class="post-metadata">

**Author:** ![ettersi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ettersi/32/6829_2.png) [@ettersi](https://discourse.julialang.org/u/ettersi)\
**Post date:** [April 20, 2023, 4:22am UTC](https://discourse.julialang.org/t/constructfrom-jl-construct-objects-without-spelling-out-their-types/97459/3 "2023-04-20T04:22:03Z")

</div>

Thanks for you input, @aplavin! I’ve decided to go ahead and [register](https://github.com/JuliaRegistries/General/pull/81719) my package.
