刚刚更新了我的项目部门,并使用 Match.jl @match 语句收到此错误。
ERROR: The type `Dates.Date` has 1 fields but the pattern expects 3 fields.
@match date begin
Date(2023, 4, 10) => true # Monday after Easter
Date(2023, 5, 1) => true # May Day?
end
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:35
[2] bind_pattern!(location::LineNumberNode, source::Expr, input::Symbol, binder::Match.BinderContext, assigned::Base.ImmutableDict{Symbol, Symbol})
@ Match ~/.julia/packages/Match/SZDEk/src/binding.jl:244
[3] bind_case(case_number::Int64, location::LineNumberNode, case::Expr, predeclared_temps::Vector{Any}, binder::Match.BinderContext)
@ Match ~/.julia/packages/Match/SZDEk/src/binding.jl:580
[4] build_automaton_core(value::Symbol, source_cases::Vector{Any}, location::LineNumberNode, predeclared_temps::Vector{Any}, binder::Match.BinderContext)
@ Match ~/.julia/packages/Match/SZDEk/src/match_cases_opt.jl:15
[5] build_automaton(location::LineNumberNode, mod::Module, value::Any, body::Expr)
@ Match ~/.julia/packages/Match/SZDEk/src/match_cases_opt.jl:149
[6] build_deduplicated_automaton
@ ~/.julia/packages/Match/SZDEk/src/match_cases_opt.jl:158 [inlined]
[7] handle_match_cases(location::LineNumberNode, mod::Module, value::Symbol, body::Expr)
@ Match ~/.julia/packages/Match/SZDEk/src/match_cases_opt.jl:477
[8] var"@match"(__source__::LineNumberNode, __module__::Module, value::Any, cases::Any)
@ Match ~/.julia/packages/Match/SZDEk/src/matchmacro.jl:114
[9] include(mod::Module, _path::String)
@ Base ./Base.jl:457
[10] include(x::String)
@ Main.Tibra ~/src/tibra/Tibra.jl/src/Tibra.jl:1
[11] top-level scope
@ ~/src/tibra/Tibra.jl/src/Tibra.jl:101
[12] include(fname::String)
@ Base.MainInclude ./client.jl:478
[13] top-level scope
@ ~/src/tibra/Tibra.jl/scripts/run_tibrax_server.jl:1
在模式中插入
Date
函数:
using Match, Dates
date = Date(2023, 5, 1)
check = @match date begin
$(Date(2023, 4, 10)) => true
$(Date(2023, 5, 1)) => false
end
@assert check == false
或者您可以使用模式的内部构造函数
Date(::Dates.UTInstant{Day})
:
date = Date(2023, 4, 10)
check = @match date begin
Date(Dates.UTInstant(Day(738620)) => true
Date(Dates.UTInstant(Day(738642)) => false
end
@assert check == true
对于 multi-case
@match
宏,Match.jl 要求模式为以下之一:
Match.jl 仅将参数数量与结构成员相同的构造函数视为此定义中的“构造函数”。它不认为“外部构造函数”是构造函数,这就是
Date(y, m, d)
是什么。您可以通过创建一个具有两个构造函数的类型来自行检查宏的工作原理:一个具有与结构体参数相同数量的参数,另一个具有其他数量的参数或具有某些不兼容类型的参数,并且@match
会抛出类似的异常:
struct Foo
a::Int
b::Int
end
Foo(x::String, y::String) = Foo(parse(Int, x), parse(Int, y))
Foo(x::Int) = Foo(x, 0)
foo = Foo(1, 0)
check = @match foo begin
Foo(1) => true
Foo(2) => false
end # throws LoadError because the number of arguments does not match the number of struct parameters
check = @match foo begin
Foo("1", "0") => true
Foo("2", "0") => false
end # throws MatchFailure, even though Foo(::String, ::String) has the right number of arguments and returns an appropriate Foo struct
check = @match foo begin
Foo(1, 0) => true
Foo(2, 0) => false
end
@assert check == true # works
但是,您可以通过简单地在
@match
宏中插入外部构造函数方法的返回值来解决此问题,如文档中所述:
check = @match foo begin
$(Foo(1)) => true # interpolates to Foo(1, 0)
$(Foo("2", "0")) => false # interpolates to Foo(2, 0)
end
@assert check == true
当然,你总是可以这样做:
check = let
if foo == Foo(1)
true
elseif foo == Foo(2)
false
end
end
@assert check == true
这基本上就是
@match
宏最终为您做的事情。