What does @kwdef do?

I stumbled upon it in Plots.jl docs. But can’t find a description anywhere.

I searched the official docs, and its pdf version. Looked at the Manual tab.

On google and discourse alike, I’m able to find posts like this one, where there’s discussion of the future of Base.@kwdef, but here I’m unsure of what it even does.

Could someone please point me in a direction?
Thank You
Cheers

2 Likes

It’s unfortunately not exported or in the manual (ref https://github.com/JuliaLang/julia/issues/33192 and https://github.com/JuliaLang/julia/issues/32659), but you can access the docstring from the help mode (type ? in the Julia prompt):

help?> Base.@kwdef
  @kwdef typedef

  This is a helper macro that automatically defines a keyword-based constructor for the type declared in the
  expression typedef, which must be a struct or mutable struct expression. The default argument is supplied by
  declaring fields of the form field::T = default or field = default. If no default is provided then the keyword
  argument becomes a required keyword argument in the resulting type constructor.

  Inner constructors can still be defined, but at least one should accept arguments in the same form as the default
  inner constructor (i.e. one positional argument per field) in order to function correctly with the keyword outer
  constructor.

  │ Julia 1.1
  │
  │  Base.@kwdef for parametric structs, and structs with supertypes requires at least Julia 1.1.

  Examples
  ≡≡≡≡≡≡≡≡≡≡

  julia> Base.@kwdef struct Foo
             a::Int = 1         # specified default
             b::String          # required keyword
         end
  Foo

  julia> Foo(b="hi")
  Foo(1, "hi")

  julia> Foo()
  ERROR: UndefKeywordError: keyword argument b not assigned
  Stacktrace:
  [...]

Edit: by the way, if you are interested in the history of it, it looks like this was first added in 2016 in https://github.com/JuliaLang/julia/pull/19473 for use within Julia Base itself, and then improved over time in https://github.com/JuliaLang/julia/pull/27987 and https://github.com/JuliaLang/julia/pull/29316 (and possibly others).

Since it is not exported nor in the manual (as reflects its origins as an internal utility), I think* this means it is not part of Julia’s public API and could be changed in a minor version, although it’s used extensively in public packages and private code, so I hope it wouldn’t be broken too much out of consideration for that. (And public package breakage is definitely taken into account when releasing new Julia versions, via PkgEval).

*documenting what constitutes the public API is itself an open PR: https://github.com/JuliaLang/julia/pull/35715

18 Likes

Many thanks, especially for the Edit. I asked for a direction, and got a map as well as some lunch for the journey. Thank you for your kindness.

12 Likes