为什么Julia参数化构造函数单行定义报错,仅多行定义可正常运行?
问题根源
这个错误是Julia 1.6及更早版本的语法解析优先级歧义导致的:
在解析单行赋值式函数(f(...) = ...形式)时,where子句的优先级低于返回类型标注和赋值运算符,你写的代码:
Device(talkfn::F, cpu::C, id_addr::Int)::Device where {C<:AbstractCPU, F<:Function} = Device(cpu, id_addr, talkfn)
会被解析器错误理解为:where子句仅作用于返回值类型Device,而不是整个函数签名,相当于:
Device(talkfn::F, cpu::C, id_addr::Int)::(Device where {C<:AbstractCPU, F<:Function}) = Device(cpu, id_addr, talkfn)
这种情况下参数签名里的F、C没有被声明为类型参数,就会抛出UndefVarError。
而你用function关键字定义多行函数时,语法结构明确,where子句会被正确识别为作用于整个方法,因此可以正常运行。
其他现象解释
- 你移除参数签名里的
::F、::C后能正常运行:是因为此时参数里没有引用未声明的F、C变量,不会触发未定义报错,Julia会自动推断参数的实际类型,不影响运行。 - 你写的
begin...end包裹单行函数体的写法仍然报错:是因为歧义出在函数签名解析阶段,和函数体的写法无关。
解决方案
有三种可行的解决方式:
- 升级Julia到1.7及以上版本,这个语法解析歧义问题已经在后续版本中修复
- 保持当前版本的话,使用
function关键字定义带类型参数的方法,就是你最后采用的写法 - 如果一定要用单行赋值式写法,给整个函数签名加括号强制
where子句的作用范围:
(Device(talkfn::F, cpu::C, id_addr::Int)::Device) where {C<:AbstractCPU, F<:Function} = Device(cpu, id_addr, talkfn)
内容的提问来源于stack exchange,提问作者POP2kr
相关产品推荐
相关产品推荐

