How can I build an inner constructor accepting keywords arguments?

I show my problem with a minimal example, say I have:

julia> @kwdef struct Foo
           x::Int = 3
           y::Int
           Foo(m, x, y) = new(m*x, m*y)
           Foo(m; x, y) = Foo(m, x, y)
       end
Foo

I’d like to expose only the two inner constructor I have inside the Foo definition and nothing else, unfortunately this doesn’t completely work:

julia> Foo(1, 2, 3)
Foo(2, 3)

julia> Foo(1; y=3)
ERROR: UndefKeywordError: keyword argument `x` not assigned
Stacktrace:
 [1] top-level scope
   @ REPL[5]:1

How can I expose those two constructor (and no others)? The second constructor doesn’t seem to play well with the @kwdef macro, but I hope there is a solution

What is m?

m in the real code is a model which decides what values for x and y are given

Indeed a better example could be

@kwdef struct Foo
           x::Int = 3
           y::Int
           Foo(m, x, y) = new(m*x, m*y)
           Foo(m; x, y) = Foo(m, x, y)
       end

so that m is actually used

This problem is unrelated to constructors. You haven’t provided any default value for x in the constructor.

1 Like

Well, actually, I’m not that familiar with @kwdef, and dislike that interface, but that seems to be the error given.

If you are going to define a kwargs interface to the type construction anyway, I would personally set the defaults in the constructor and avoid the macro.

1 Like

yes, you are right, I think that I should use something like

struct Foo
    x::Int
    y::Int
    Foo(m, x, y) = new(m*x, m*y)
    Foo(m; x = 3, y) = Foo(m, x, y)
end

which seems to work fine:

julia> Foo(1, 2, 3)
Foo(2, 3)

julia> Foo(1; x=2, y=3)
Foo(2, 3)

julia> Foo(1; y=3)
Foo(3, 3)

In my actual problem I have to generate these things with a macro from a different syntax, so I hoped there was something simpler, but this isn’t actually that bad, thank you a lot!