# Making new a bit more automatic

**URL:** <https://discourse.julialang.org/t/making-new-a-bit-more-automatic/22905>\
**Category:** General Usage\
**Tags:** question\
**Created:** [April 8, 2019, 8:19am UTC](https://discourse.julialang.org/t/making-new-a-bit-more-automatic/22905 "2019-04-08T08:19:38Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [April 8, 2019, 8:19am UTC](https://discourse.julialang.org/t/making-new-a-bit-more-automatic/22905/1 "2019-04-08T08:19:38Z")

</div>

Consider a definition with the outer-only constructor

```julia
Base.@kwdef struct Foo{T,S}
    a::T
    b::S
    function Foo(a::T, b::S) where {T,S}
        @assert a > 0 && b > 0
        new{T,S}(a, b)
    end
end

```

where `T` and `S` are not used for anything, just parametrizing `new`. An alternative would be

```julia
Base.@kwdef struct Foo2{T,S}
    a::T
    b::S
    function Foo2(a, b)
        @assert a > 0 && b > 0
        new{typeof(a),typeof(b)}(a, b)
    end
end

```

Is there a way to get rid of the boilerplate? I tried

```julia
Base.@kwdef struct Foo3{T,S}
    a::T
    b::S
    function Foo3(a, b)
        @assert a > 0 && b > 0
        args = (a, b)
        new{map(typeof, args)...}(args...)
    end
end

```

but got

```julia
ERROR: syntax: too few type parameters specified in "new{...}"

```

---

<div class="post-metadata">

**Author:** ![Christopher\_Fisher](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/christopher_fisher/32/26132_2.png) [@Christopher\_Fisher](https://discourse.julialang.org/u/Christopher_Fisher)\
**Post date:** [April 8, 2019, 8:30am UTC](https://discourse.julialang.org/t/making-new-a-bit-more-automatic/22905/2 "2019-04-08T08:30:08Z")

</div>

I encountered this limitation before and could not figure out a way to automate the process. I think something along the lines of what you proposed would be a useful addition to the language.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [April 8, 2019, 8:39am UTC](https://discourse.julialang.org/t/making-new-a-bit-more-automatic/22905/3 "2019-04-08T08:39:56Z")

</div>

I don’t think one can make it entirely automatic, consider eg

```julia
Base.@kwdef struct Foo{S,T} # NOTE ORDER
    a::T
    b::S
    function Foo(a::T, b::S) where {T,S}
        @assert a > 0 && b > 0
        new{S,T}(a, b) # NOTE ORDER
    end
end

```

What is missing is a nice way to compose

1. the outermost layer of keyword arguments, with defaults,

2. the default outer constructor which nicely promotes,

3. an inner constructor which can call an _arbitrary_ block of code that has at least _access_ to the fields (not necessarily transformations, generation, etc, even though that would be nice).

Currently `Base` provides an all-or-nothing approach. Which may be fine, this is a job for a package. Currently none of the options available provide a full solution. But the problem is quite complex and I need to think more about what I want exactly, and whether it can be generalized enough to be packaged.

The **immediate** question I don’t get though is why the `Foo3` inner constructor code doesn’t work. Is it a bug?

---

<div class="post-metadata">

**Author:** ![mzaffalon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mzaffalon/32/214168_2.png) [@mzaffalon](https://discourse.julialang.org/u/mzaffalon)\
**Post date:** [April 8, 2019, 9:10am UTC](https://discourse.julialang.org/t/making-new-a-bit-more-automatic/22905/4 "2019-04-08T09:10:36Z")

</div>

Unrelated (and most likely just a slip): `@assert` in your code should be replaced by throwing an exception: see the warning box in the [doc](https://docs.julialang.org/en/v1/base/base/#Base.@assert).

---

<div class="post-metadata">

**Author:** ![greg\_plowman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/greg_plowman/32/8100_2.png) [@greg\_plowman](https://discourse.julialang.org/u/greg_plowman)\
**Post date:** [April 8, 2019, 9:19am UTC](https://discourse.julialang.org/t/making-new-a-bit-more-automatic/22905/5 "2019-04-08T09:19:41Z")

</div>

> [@Tamas\_Papp](#):
>
> The **immediate** question I don’t get though is why the `Foo3` inner constructor code doesn’t work. Is it a bug?

I don’t know if it’s a bug, but it seems to be unsupported. Without `@kwdef`, I get this:

```julia
Julia-1.1.0> struct Foo3{T,S}
                 a::T
                 b::S
                 function Foo3(a, b)
                     @assert a > 0 && b > 0
                     args = (a, b)
                     new{map(typeof, args)...}(args...)
                 end
             end
ERROR: syntax: ... is not supported inside "new"

```

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [April 8, 2019, 10:46am UTC](https://discourse.julialang.org/t/making-new-a-bit-more-automatic/22905/6 "2019-04-08T10:46:28Z")

</div>

Thanks, there was even an issue:

> <https://github.com/JuliaLang/julia/issues/16079>
>
> Splatting doesn't work inside of internal constructors, @nalimilan thinks this i…s because it is getting confused for varargs syntax? Or is this by design?
> 
> \`\`\` julia
> \# splatting.jl
> type foo
> x::UInt8
> y::Int16
> z::Int64
> 
> foo() = new(\[0 for i in 1:3\]...)
> end
> \`\`\`
> 
> \`\`\`
> $ julia splatting.jl
> ERROR: LoadError: syntax: ... is not supported inside "new"
> in include at /usr/local/Cellar/julia/0.4.5/lib/julia/sys.dylib
> in include\_from\_node1 at /usr/local/Cellar/julia/0.4.5/lib/julia/sys.dylib
> in process\_options at /usr/local/Cellar/julia/0.4.5/lib/julia/sys.dylib
> in \_start at /usr/local/Cellar/julia/0.4.5/lib/julia/sys.dylib
> while loading /Users/sabae/splatting.jl, in expression starting on line 8
> \`\`\`
