使用Julia struct计算RMSE时遇UndefVarError: @property未定义问题
Julia RMSE Struct 报错问题解决
问题重现
尝试用Julia编写类似Python类的struct计算数组RMSE,代码如下:
struct RMSE _array1::Array _array2::Array function RMSE(array1::Array, array2::Array) new(array1, array2) end # getter function for array1 function RMSE.array1(r::RMSE) return r._array1 end # setter function for array1 function RMSE.array1(r::RMSE, value::Array) r._array1 = value end # getter function for array2 function RMSE.array2(r::RMSE) return r._array2 end # setter function for array2 function RMSE.array2(r::RMSE, value::Array) r._array2 = value end # @property macro to for array1 and array2 with both a getter and a setter @property array1() @property array2() # Calculating the RMSE between the array1 and array2 function RMSE.calculate(r::RMSE) sum_squares = sum((r.array1 - r.array2).^2) rmse = sqrt(sum_squares / length(r.array1)) return rmse end end r = RMSE([1, 2, 3], [1, 2, 3]) r.array1 = [4, 5, 6] r.array2 = [7, 8, 9] rmse = r.calculate println(rmse)
运行后报错:
ERROR: LoadError: UndefVarError: @property not defined in expression starting at /home/Julia/rmse_struct.jl:30 in expression starting at /home/Julia/rmse_struct.jl:1
使用Julia 1.7.2版本,误以为@property是Julia 0.7+内置功能,询问错误原因。
问题分析与解决
核心错误原因
Julia标准库中没有内置@property宏,该宏来自第三方包Properties.jl,直接使用会触发未定义错误。此外代码还有两个隐性问题:
- 默认
struct是不可变类型,无法修改字段值,setter函数会执行失败; - 调用
calculate时未加括号,仅获取函数对象而非执行计算。
修正方案
方案1:原生Julia实现(无需第三方包)
用mutable struct定义可变类型,通过自定义方法实现属性访问:
mutable struct RMSE _array1::Array _array2::Array function RMSE(array1::Array, array2::Array) @assert length(array1) == length(array2) "两个数组长度必须相等" new(array1, array2) end end # array1的getter与setter function array1(r::RMSE) return r._array1 end function array1!(r::RMSE, value::Array) @assert length(value) == length(r._array2) "新数组长度需与原数组一致" r._array1 = value end # array2的getter与setter function array2(r::RMSE) return r._array2 end function array2!(r::RMSE, value::Array) @assert length(value) == length(r._array1) "新数组长度需与原数组一致" r._array2 = value end # RMSE计算方法 function calculate(r::RMSE) sum_squares = sum((array1(r) - array2(r)).^2) return sqrt(sum_squares / length(array1(r))) end # 测试代码 r = RMSE([1,2,3], [1,2,3]) array1!(r, [4,5,6]) array2!(r, [7,8,9]) rmse = calculate(r) println(rmse) # 输出:5.196152422706632
方案2:使用Properties.jl第三方包
若坚持用@property宏,需先安装包:
using Pkg Pkg.add("Properties")
修改后的代码:
using Properties mutable struct RMSE _array1::Array _array2::Array function RMSE(array1::Array, array2::Array) @assert length(array1) == length(array2) "两个数组长度必须相等" new(array1, array2) end # 定义array1的属性访问 @property array1() = getfield(self, :_array1) @property array1!(value::Array) = begin @assert length(value) == length(self._array2) "新数组长度需一致" setfield!(self, :_array1, value) end # 定义array2的属性访问 @property array2() = getfield(self, :_array2) @property array2!(value::Array) = begin @assert length(value) == length(self._array1) "新数组长度需一致" setfield!(self, :_array2, value) end # RMSE计算方法 function calculate(r::RMSE) sum_squares = sum((r.array1 - r.array2).^2) return sqrt(sum_squares / length(r.array1)) end end # 测试代码 r = RMSE([1,2,3], [1,2,3]) r.array1 = [4,5,6] r.array2 = [7,8,9] rmse = r.calculate() println(rmse)
关键注意事项
- 要修改struct字段必须使用
mutable struct,默认struct不可变; - 调用方法时必须加括号(如
r.calculate()),否则仅返回函数对象; - 添加数组长度校验可避免后续计算出错。
内容的提问来源于stack exchange,提问作者naughty_waves
相关产品推荐
相关产品推荐

