Julia 朱莉娅:如何在结构中使用@assert宏@带_kw vs Base@kwdef

Julia 朱莉娅:如何在结构中使用@assert宏@带_kw vs Base@kwdef,julia,Julia,我想将@assert宏与结构一起使用packageParameters中的@with_kw宏可以在结构顶部没有显式方法的情况下使用,而Base@kwdef需要显式方法。我理解正确吗? # 1. outer constructor with "semi-colon" keyword + no keyword macro + @assert struct myStruct1 a :: Float64 end function myStruct1(;a::Float64=1

我想将@assert宏与结构一起使用package
Parameters
中的@with_kw宏可以在结构顶部没有显式方法的情况下使用,而Base@kwdef需要显式方法。我理解正确吗?

# 1. outer constructor with "semi-colon" keyword + no keyword macro + @assert
struct myStruct1
    a :: Float64
end
function myStruct1(;a::Float64=1.0)
    @assert a > 0 "must be positive"
    myStruct1(a)
end
myStruct1().a
## 1.0 
myStruct1(a = -1.0).a
## ERROR: LoadError: AssertionError: must be positive

# 2.1. Base.@kwdef + no outer constructor + @assert
Base.@kwdef struct myStruct2
    a :: Float64 = 1.0
    @assert a > 0 "must be positive"  # was hoping this would work
end 
myStruct2().a
## ERROR: LoadError: UndefVarError: a not defined

# 2.2. Base.@kwdef + outer constructor + @assert
Base.@kwdef struct myStruct22
    a :: Float64 = 1.0
end 
function myStruct22(;a::Float64=1.0)  # explicit method just to @assert 
    @assert a > 0 "must be positive"
    myStruct22(a)
end
myStruct22().a
## 1.0
myStruct22(a = -1.0).a
## ERROR: LoadError: AssertionError: must be positive

# 2.3. @with_kw + outer constructor + @assert
using Parameters
@with_kw struct myStruct23
    a :: Float64 = 1.0
    @assert a > 0 "must be positive"  # works without explicit method
end 
myStruct23().a
## 1.0
myStruct23(a = -1.0).a
# ERROR: LoadError: AssertionError: must be positive

目前,
Base.@kwdef
不支持此功能,因为正如您所说,它使用外部构造函数。您可以使用
@macroexpand
宏检查生成的代码:

julia> @macroexpand Base.@kwdef struct myStruct2
           a :: Float64 = 1.0
           @assert a > 0 "must be positive"  # was hoping this would work
       end
quote
    #= util.jl:472 =#
    begin
        $(Expr(:meta, :doc))
        struct myStruct2
            #= REPL[3]:2 =#
            a::Float64
            #= REPL[3]:3 =#
            if a > 0
                nothing
            else
                Base.throw(Base.AssertionError("must be positive"))
            end
        end
    end
    #= util.jl:473 =#
    myStruct2(; a = 1.0) = begin
            #= util.jl:450 =#
            myStruct2(a)
        end
end

正如您所看到的,断言代码在结构定义中,而不是在外部构造函数中。

非常感谢!从0.5版开始,我就没有使用过Julia,我不知道/不记得关于
@macroexpand
。非常有用。