更新依赖后Match.jl @match匹配Dates.Date出现字段不匹配错误
Match.jl 使用@match匹配Dates.Date时报错:类型
Dates.Date仅有1个字段,但模式期望3个字段 问题重现
执行以下代码时触发错误:
@match date begin Date(2023, 4, 10) => true # 复活节后的周一 Date(2023, 5, 1) => true # 劳动节? end
错误信息:
错误:类型`Dates.Date`仅有1个字段,但模式期望3个字段。
完整堆栈跟踪:
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
原因说明
Dates.Date本质是单字段结构体,内部仅存储一个代表纪元天数的整数,并非包含年、月、日三个独立字段。更新Match.jl依赖后,版本对结构体字段匹配的校验更严格,直接用Date(y,m,d)作为匹配模式会被解析为期望匹配一个三字段结构体,因此触发错误。
解决方案
方案1:直接比较Date对象
在匹配分支中添加条件判断,直接对比目标Date值:
@match date begin d::Date if d == Date(2023, 4, 10) => true d::Date if d == Date(2023, 5, 1) => true _ => false # 处理其他情况 end
方案2:提取年月日字段后匹配
将Date对象转换为年、月、日的元组,再进行模式匹配:
using Dates @match (year(date), month(date), day(date)) begin (2023, 4, 10) => true (2023, 5, 1) => true _ => false end
方案3:自定义Match.jl匹配规则
如果需要频繁使用Date(y,m,d)形式的匹配,可以给Match.jl添加自定义匹配逻辑:
using Match, Dates # 定义Date的匹配规则 Match.@matchable Date(y, m, d) = Date(y, m, d) == x # 之后即可按原写法使用 @match date begin Date(2023, 4, 10) => true Date(2023, 5, 1) => true _ => false end
内容的提问来源于stack exchange,提问作者BAR
相关产品推荐
相关产品推荐

