Using a `new` constructor with Parameters.jl `@with_kw`

I’d like to do something like this.

using Parameters

struct Cat
    breed
    colour
    age
    weight
    name
end

@with_kw struct Pet
    name
    kind
    age
    function Pet(cat::Cat)
        new(name= cat.name, kind = typeof(cat), age =  cat.age)
    end
end

fluffy = Cat("Fluffy", "White", 2, 10, "Fluffy")
pet = Pet(cat)

Here, there’s a constructor to easily make Pet instances from a Cat instance, but this gives the error

ERROR: syntax: "new" does not accept keyword arguments around

How can I implement this correctly?

julia> using Parameters

julia> struct Cat
           breed
           colour
           age
           weight
           name
       end

julia> @with_kw struct Pet
           name
           kind
           age
       end
Pet

julia> Pet(c::Cat) = Pet(name=c.name, kind=typeof(c), age=c.age)
Pet

julia> c = Cat("None", "Black", 5, 5.0, "John")
Cat("None", "Black", 5, 5.0, "John")

julia> Pet(c)
Pet
  name: String "John"
  kind: Cat <: Any
  age: Int64 5


You only need inner constructors if you want a Pet(a,b,c) constructor, which may be ambiguous with the default constructor.

Thanks for your reply, while this is a sensible answer there’s two reasons why I’d rather not use this method:

  1. I’d prefer for the constructor to be defined in the struct, it seems like a nicer syntax, and it is also more in keeping with a non-Parameters.jl approach
  2. This method doesn’t work within Pluto notebooks, I appreciate I didn’t mention this in the initial question though

That is not the most common view. Inner constructions are the exception, not the rule.

You can just put them in a begin... end block, as suggested by the error message.

Anyway, both these are styling choices, you are not really limited by the functionality. But you can use an inner constructor without the keyword arguments, if you want:

julia> @with_kw struct Pet
           name
           kind
           age
           Pet(c::Cat) = new(c.name, typeof(c), c.age)
       end

julia> c = Cat("None", "Black", 5, 5.0, "John")
Cat("None", "Black", 5, 5.0, "John")

julia> Pet(c)
Pet
  name: String "John"
  kind: Cat <: Any
  age: Int64 5