Skip to content

Commit de85ef3

Browse files
author
Frankie Robertson
committed
Add @kw_only macro
`@kw_only` behaves the same as `@with_kw` but does not declare a default constructor when no inner constructor is found.
1 parent 029dad2 commit de85ef3

File tree

2 files changed

+52
-7
lines changed

2 files changed

+52
-7
lines changed

src/Parameters.jl

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ import Base: @__doc__
4545
import OrderedCollections: OrderedDict
4646
using UnPack: @unpack, @pack!
4747

48-
export @with_kw, @with_kw_noshow, type2dict, reconstruct, @unpack, @pack!, @pack, @consts
48+
export @with_kw, @kw_only, @with_kw_noshow, type2dict, reconstruct, @unpack, @pack!, @pack, @consts
4949

5050
## Parser helpers
5151
#################
@@ -326,7 +326,7 @@ macro pack_MM(varname)
326326
end
327327
```
328328
"""
329-
function with_kw(typedef, mod::Module, withshow=true)
329+
function with_kw(typedef, mod::Module, withshow=true, allow_default=true)
330330
if typedef.head==:tuple # named-tuple
331331
withshow==false && error("`@with_kw_noshow` not supported for named tuples")
332332
return with_kw_nt(typedef, mod)
@@ -486,18 +486,27 @@ function with_kw(typedef, mod::Module, withshow=true)
486486
push!(args, k)
487487
push!(kwargs.args, Expr(:kw,k,w))
488488
end
489-
if length(typparas)>0
490-
tps = stripsubtypes(typparas)
491-
innerc = :( $tn{$(tps...)}($kwargs) where {$(tps...)} = $tn{$(tps...)}($(args...)))
489+
if allow_default
490+
if length(typparas)>0
491+
tps = stripsubtypes(typparas)
492+
innerc = :( $tn{$(tps...)}($kwargs) where {$(tps...)} = $tn{$(tps...)}($(args...)))
493+
else
494+
innerc = :($tn($kwargs) = $tn($(args...)) )
495+
end
492496
else
493-
innerc = :($tn($kwargs) = $tn($(args...)) )
497+
if length(typparas)>0
498+
tps = stripsubtypes(typparas)
499+
innerc = :( $tn{$(tps...)}($kwargs) where {$(tps...)} = new{$(tps...)}($(args...)))
500+
else
501+
innerc = :($tn($kwargs) = new($(args...)) )
502+
end
494503
end
495504
push!(typ.args[3].args, innerc)
496505

497506
# Inner positional constructor: only make it if no inner
498507
# constructors are user-defined. If one or several are defined,
499508
# assume that one has the standard positional signature.
500-
if length(inner_constructors)==0
509+
if length(inner_constructors)==0 && allow_default
501510
if length(typparas)>0
502511
tps = stripsubtypes(typparas)
503512
innerc2 = :( $tn{$(tps...)}($(args...)) where {$(tps...)} = new{$(tps...)}($(args...)) )
@@ -679,6 +688,14 @@ macro with_kw(args...)
679688
""")
680689
end
681690

691+
"""
692+
As `@with_kw` but does not declare a default constructor when no inner
693+
constructor is found.
694+
"""
695+
macro kw_only(typedef)
696+
return esc(with_kw(typedef, __module__, true, false))
697+
end
698+
682699
"""
683700
As `@with_kw` but does not define a `show` method to avoid annoying
684701
redefinition warnings.

test/runtests.jl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,34 @@ const TMT1_3 = MT1_3{Int} # Julia bug https://github.com/JuliaLang/julia/issues/
8181
@test "Field r Default: 4\n" == Markdown.plain(REPL.fielddoc(TMT1_3, :r))
8282
@test "A field Default: sdaf\n" == Markdown.plain(REPL.fielddoc(TMT1_3, :c))
8383

84+
# no positional inner constructor
85+
@kw_only struct KWO
86+
foo
87+
bar
88+
end
89+
90+
function KWO(args...)
91+
global outer_constructor_called = true
92+
KWO(; foo="foo", bar="bar")
93+
end
94+
95+
outer_constructor_called = false
96+
kwo = KWO(42)
97+
@test outer_constructor_called == true
98+
@test kwo.foo == "foo"
99+
@test kwo.bar == "bar"
100+
101+
outer_constructor_called = false
102+
kwo2 = KWO(42, 43)
103+
@test outer_constructor_called == true
104+
@test kwo2.foo == "foo"
105+
@test kwo2.bar == "bar"
106+
107+
outer_constructor_called = false
108+
kwo3 = KWO(; foo=42, bar=43)
109+
@test outer_constructor_called == false
110+
@test kwo3.foo == 42
111+
@test kwo3.bar == 43
84112

85113
# parameter-less
86114
@with_kw_noshow mutable struct MT2

0 commit comments

Comments
 (0)