我是朱莉娅的新手,所以这可能是个愚蠢的问题。
我有一个类型,函数作为属性,如下所示:
struct exampleStruct
someAtrribute::someType
theFunction::Function
end是否有适当的方法进一步指定有关参数类型和返回类型的theFunction类型?在我的例子中,我确信theFunction的实例应该只接受Float64类型的参数,并具有Float64类型的返回值,例如,我可以编写类似于theFunction::Function{Float64,...}{Float64}的东西。
我想您可能会制作一个Function的子类型,但我觉得这需要深入挖掘。
发布于 2022-07-10 06:36:43
在Julia中,每个函数都有其独特的类型。例如,如果您使用函数sin
julia> typeof(sin)
typeof(sin) (singleton type of function sin, subtype of Function)您可以看到它的类型显示为typeof(sin)。此外,您还会得到这样的信息,即此类型是抽象类型Function的子类型。您可以通过以下方法来检查:
julia> supertype(typeof(sin))
Function在您当前的Julia会话中,您可以通过以下方式找到所有Funcion类型的子类型:
julia> subtypes(Function)
11259-element Vector{Any}:
ArgTools.var"#1#11"
ArgTools.var"#10#20"
ArgTools.var"#2#12"
ArgTools.var"#21#31"
⋮
typeof(⊉) (singleton type of function ⊉, subtype of Function)
typeof(⊊) (singleton type of function ⊊, subtype of Function)
typeof(⊋) (singleton type of function ⊋, subtype of Function)(这是一个新的Julia 1.7.2会话的输出)
现在,必须了解函数类型与其名称和定义函数的模块相关联。例如,让我import Statistics模块:
julia> import Statistics
julia> typeof(Statistics.mean)
typeof(Statistics.mean) (singleton type of function mean, subtype of Function)实际上,您可以提取定义函数类型的类型名称和模块:
julia> Base.nameof(sin)
:sin
julia> Base.parentmodule(sin)
Base
julia> Base.nameof(Statistics.mean)
:mean
julia> Base.parentmodule(Statistics.mean)
Statistics(这种区别很重要,因为在Julia中,许多函数具有相同的名称,但定义在不同的模块中)
因此,您可以认为函数类型是由函数名和模块定义的。如您所见,函数类型的定义中没有参数类型或返回值类型。为什么会这样呢?原因是朱莉娅的一个函数可以有很多方法。函数类型本身不提供任何功能--它只是定义函数名称的名称和模块。只有在将方法添加到函数之后,才有可以执行的内容。由于您可以拥有一个给定函数的许多方法,所以每个方法都可以有不同类型的参数和不同的返回值。
让我们检查一下Statistics.mean它定义了哪些方法:
julia> methods(Statistics.mean)
# 5 methods for generic function "mean":
[1] mean(r::AbstractRange{<:Real}) in Statistics
[2] mean(A::AbstractArray; dims) in Statistics
[3] mean(itr) in Statistics
[4] mean(f, A::AbstractArray; dims) in Statistics
[5] mean(f, itr) in Statistics以后还可以将方法添加到函数中。下面是一个示例:
julia> function f end
f (generic function with 0 methods)
julia> methods(f)
# 0 methods for generic function "f":
julia> Base.nameof(f)
:f
julia> Base.parentmodule(f)
Main
julia> f(x::Integer) = 10x
f (generic function with 1 method)
julia> methods(f)
# 1 method for generic function "f":
[1] f(x::Integer) in Main at REPL[26]:1
julia> f(x::String) = x^10
f (generic function with 2 methods)
julia> methods(f)
# 2 methods for generic function "f":
[1] f(x::Integer) in Main at REPL[26]:1
[2] f(x::String) in Main at REPL[28]:1(在这个示例中,我向您展示了您甚至可以使用一种最初没有定义方法的新类型来定义一个函数)
总结如下:
Function型;Function抽象类型的子类型;由于这些原因,在Julia中不可能指定有关参数类型和返回类型的函数类型(您只能指定函数类型定义的名称和模块)。
关于@jling的评论。
你的定义:
struct exampleStruct
someAtrribute::someType
theFunction::Function
end是正确的,并将接受任何函数作为theFunction参数。但是,建议您创建一个参数类型:
struct exampleStruct{T<:Function}
someAtrribute::someType
theFunction::T
end此建议与以后使用exampleStruct的性能有关。如果字段类型的theFunction是Function,这是一个抽象类型,并且使用抽象类型作为容器中的参数会降低代码的性能,正如“朱莉娅手册”的本节中所解释的那样。但是,如果您的代码不是性能关键,那么您应该可以使用您的原始定义。
最后,请记住,在Julia中,有些可调用类不是Function类型的子类型。两个最重要的情况是类型构造函数,例如,您可以调用Int构造函数,但Int不是Function的子类型,第二个是函子,如“朱莉娅手册”的本节中所解释的那样。
这意味着,在exampleStruct的定义中,如果将第二个字段类型限制为Function,将不允许将一些可调用项作为其参数传递。在您的情况下,这可能不是一个问题,但是当用户试图创建将函数存储为他们的字段的数据结构时,这是一个常见的问题。
发布于 2022-07-09 20:44:30
我对朱莉娅也很陌生。我还在学着用多重调度和O-O的方式来思考。类型并不完全是对象。您可以像函数一样使结构可调用,但它不支持O-O方法中类似于结构的对象中的多个函数规范。相反,范例是编写以类型作为参数的函数。在你的情况下,就像:
函数theFunction{x::exampleStruct,y等}
发布于 2022-07-11 22:05:36
是的,如果你深入挖掘,肯定有办法做到这一点,但问题是:你会那样利用朱莉娅吗?那么最好还是坚持使用Python (或其他语言),因为您不会使用Julia所能提供的全部功能。
对于您的源代码,我有一个问题:exampleStruct是"earth“中唯一与名为theFunction的函数一起工作的类型吗?如果答案是否定的,关键是为什么要费心将thefunction绑定到exampleStruct。如果您想要享受语言的风格,可以使用多重分派.。
在外部定义theFunction并为exampleStruct实现它。然后,当您需要/拥有另一种使用theFunction的类型时,返回并通过多个分派简单地扩展theFunction;这样您就可以与朱莉娅同步,并为自己节省语言设计所不需要的“不必要”的复杂性。
朱莉娅基模中的iterate函数就是一个很好的例子。
julia> Base.iterate
iterate (generic function with 230 methods)是的,您看到了正确的结果:230方法仅用于一个函数。所以你看,你的问题不是愚蠢的,它只是想揭示朱莉娅的美丽。
iterate函数被分派给不同类型的230。这是非常容易管理和扩展的;如果您有一个bug,只需转到由iterate实现的导致错误的类型,然后修复它。这样,您可以轻松地添加新类型,然后扩展iterate函数。如果你在一个经典的OOP风格的中这么做,你会这么容易吗?是的,只有当你是一个老手,并且要花一个月的时间来管理继承、依赖和所有这些东西时,你才能做到这一点,只为了修复一个很可能是由一种类型引起的错误。
所以,您的问题是明智的;当在类型中定义theFunction时,您的multiple dispatch会很好地在它上工作;但是当您想要扩展时,multiple dispatch将是您的最佳选择。
https://stackoverflow.com/questions/72924225
复制相似问题