需要Julia中的类型声明

问题描述 投票:10回答:1

在Julia中(例如在模块或包中)是否有任何明确要求类型 必须 被声明的方法?是否例如PackageCompilerLint.jl是否支持此类检查?更广泛地讲,Julia标准发行版本身是否提供任何可以帮助检查此要求的静态代码分析器或等效项?

作为一个激励性的例子,假设我们要确保不断增长的生产代码库仅接受始终为[[声明的类型的代码,假设是带有类型声明的大型代码库往往更多可维护的。

如果我们要强制执行该条件,Julia在其标准发行版中是否提供任何机制来要求类型声明或帮助实现该目标? (例如,是否可以通过短绒棉纸,提交钩子或类似的东西进行检查?)
compilation julia lint static-typing dynamic-typing
1个回答
9
投票
这是一个有趣的问题。关键的问题是我们定义为

声明的类型。如果您的意思是每个方法定义中都有一个::SomeType语句,则这样做有些棘手,因为在Julia中动态代码生成的可能性不同。也许从这个意义上讲,有一个完整的解决方案,但我不知道(我想学习)。

尽管我想到的事情似乎相对简单一些,是检查模块中定义的任何方法是否接受Any作为其参数。这类似于但不等同于先前的声明,如下所示:

julia> z1(x::Any) = 1 z1 (generic function with 1 method) julia> z2(x) = 1 z2 (generic function with 1 method) julia> methods(z1) # 1 method for generic function "z1": [1] z1(x) in Main at REPL[1]:1 julia> methods(z2) # 1 method for generic function "z2": [1] z2(x) in Main at REPL[2]:1

methods函数的外观相同,因为两个函数的签名都将x接受为Any

现在检查模块/包中是否有任何方法接受Any作为其中定义的任何方法的参数,可以使用类似以下代码的内容(我没有对其进行广泛的测试,因为我已经将其写下来,但似乎似乎涵盖了可能的情况):

function check_declared(m::Module, f::Function) for mf in methods(f).ms if mf.module == m if mf.sig isa UnionAll b = mf.sig.body else b = mf.sig end x = getfield(b, 3) for i in 2:length(x) if x[i] == Any println(mf) break end end end end end function check_declared(m::Module) for n in names(m) try f = m.eval(n) if f isa Function check_declared(m, f) end catch # modules sometimes return names that cannot be evaluated in their scope end end end

现在在Base.Iterators模块上运行它会得到:

julia> check_declared(Iterators) cycle(xs) in Base.Iterators at iterators.jl:672 drop(xs, n::Integer) in Base.Iterators at iterators.jl:628 enumerate(iter) in Base.Iterators at iterators.jl:133 flatten(itr) in Base.Iterators at iterators.jl:869 repeated(x) in Base.Iterators at iterators.jl:694 repeated(x, n::Integer) in Base.Iterators at iterators.jl:714 rest(itr::Base.Iterators.Rest, state) in Base.Iterators at iterators.jl:465 rest(itr) in Base.Iterators at iterators.jl:466 rest(itr, state) in Base.Iterators at iterators.jl:464 take(xs, n::Integer) in Base.Iterators at iterators.jl:572

以及当您检查您得到的DataStructures.jl包:

julia> check_declared(DataStructures) compare(c::DataStructures.LessThan, x, y) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\heaps.jl:66 compare(c::DataStructures.GreaterThan, x, y) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\heaps.jl:67 cons(h, t::LinkedList{T}) where T in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\list.jl:13 dec!(ct::Accumulator, x, a::Number) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\accumulator.jl:86 dequeue!(pq::PriorityQueue, key) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\priorityqueue.jl:288 dequeue_pair!(pq::PriorityQueue, key) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\priorityqueue.jl:328 enqueue!(s::Queue, x) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\queue.jl:28 findkey(t::DataStructures.BalancedTree23, k) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\balanced_tree.jl:277 findkey(m::SortedDict, k_) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\sorted_dict.jl:245 findkey(m::SortedSet, k_) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\sorted_set.jl:91 heappush!(xs::AbstractArray, x) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\heaps\arrays_as_heaps.jl:71 heappush!(xs::AbstractArray, x, o::Base.Order.Ordering) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\heaps\arrays_as_heaps.jl:71 inc!(ct::Accumulator, x, a::Number) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\accumulator.jl:68 incdec!(ft::FenwickTree{T}, left::Integer, right::Integer, val) where T in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\fenwick.jl:64 nil(T) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\list.jl:15 nlargest(acc::Accumulator, n) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\accumulator.jl:161 nsmallest(acc::Accumulator, n) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\accumulator.jl:175 reset!(ct::Accumulator{#s14,V} where #s14, x) where V in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\accumulator.jl:131 searchequalrange(m::SortedMultiDict, k_) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\sorted_multi_dict.jl:226 searchsortedafter(m::Union{SortedDict, SortedMultiDict, SortedSet}, k_) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\tokens2.jl:154 sizehint!(d::RobinDict, newsz) in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\robin_dict.jl:231 update!(h::MutableBinaryHeap{T,Comp} where Comp, i::Int64, v) where T in DataStructures at D:\AppData\.julia\packages\DataStructures\iymwN\src\heaps\mutable_binary_heap.jl:250

我提出的并不是您问题的完整解决方案,但我发现它对自己很有用,因此我想与他人分享。

编辑

上面的代码仅接受fFunction。通常,您可以具有可调用的类型。然后,可以将check_declared(m::Module, f::Function)签名更改为check_declared(m::Module, f)(实际上,该函数本身将允许Any作为第二个参数:)),并将所有求值的名称传递给该函数。然后,您将必须检查methods(f)在函数内部是否具有正length(因为不可调用的methods返回长度为0的值)。
© www.soinside.com 2019 - 2024. All rights reserved.