在Julia中,我想使用一个可变的结构,该结构具有一个类型为Function的属性,该函数将带有参数:
mutable struct Class_example
function_with_arguments::Function
some_attribute::Int
function Class_example() new() end
function Class_example(function_wa::Function, some_a::Int)
this = new()
this.function_with_arguments = function_wa
this.some_attribute = some_a
this
end
end
我也想对该可变结构执行操作:
function do_action_on_class(Class::Class_example)
return Class.function_with_arguments(Class.some_attribute ,2.0, true)
end
然后我定义一个旨在成为我的类属性的函数:
function do_something_function(arg1::Int, arg2::Float64, arg3::Bool)
if arg2 < 5.0
for i in 1:arg1
# Do Something Interesting
@show arg3
end
end
return 1
end
最后,function_whith_arguments
将在我的整个项目中启动大量时间,这只是一个最小的示例,因此我希望所有这些代码都非常快速。这就是为什么我根据Julia的文档Performance Tips
但是,@code_warntype告诉了我
body::Any
15 1 ─ %1 = (Base.getfield)(Class, :function_with_arguments)::Function
getproperty
%2 = (Base.getfield)(Class, :some_attribute)::Int64
%3 = (%1)(%2, 2.0, true)::Any │
return %3
此处::Function
和两个::Any
为红色,表明Julia可以通过更好的实现来提高代码的性能。那么正确的实现是什么?我应该如何在可变结构中将属性function_whith_arguments声明为Function类型?
整个代码均可编译:
mutable struct Class_example
function_with_arguments::Function
some_attribute::Int
function Class_example() new() end
function Class_example(function_wa::Function, some_a::Int)
this = new()
this.function_with_arguments = function_wa
this.some_attribute = some_a
this
end
end
function do_action_on_class(Class::Class_example)
return Class.function_with_arguments(Class.some_attribute ,2.0, true)
end
function do_something_function(arg1::Int, arg2::Float64, arg3::Bool)
if arg2 < 5.0
for i in 1:arg1
# Do Something Interesting
@show arg3
end
end
return 1
end
function main()
class::Class_example = Class_example(do_something_function, 4)
@code_warntype do_action_on_class(class)
end
main()
答案 0 :(得分:5)
这将是有效的(可以推断)。请注意,我只修改(并重命名)了类型。
mutable struct MyClass{F<:Function}
function_with_arguments::F
some_attribute::Int
end
function do_action_on_class(Class::MyClass)
return Class.function_with_arguments(Class.some_attribute ,2.0, true)
end
function do_something_function(arg1::Int, arg2::Float64, arg3::Bool)
if arg2 < 5.0
for i in 1:arg1
# Do Something Interesting
@show arg3
end
end
return 1
end
function main()
class::MyClass = MyClass(do_something_function, 4)
@code_warntype do_action_on_class(class)
end
main()
我做了什么?
如果您关心性能,则应该never have fields of an abstract type和isabstracttype(Function) == true
。相反,您应该在该字段类型上进行参数化(上面的F
,可以是任何函数。请注意,isconcretetype(typeof(sin)) == true
)。这样,对于MyCall
的任何特定实例,在编译时就可以知道每个字段的确切具体类型。
性能的Irelevant,但:不需要将所有参数都分配给所有字段的构造函数。这样的constructor是默认隐式定义的。
您可以阅读有关参数类型here的更多信息。
顺便提一句,您所做的工作很像尝试用Julia编写OO风格。我建议不要这样做,而应使用Julia并使用多次调度的Julia方法。