นี่เป็นคำถามที่น่าสนใจ คำถามที่สำคัญคือสิ่งที่เรากำหนดเป็นประเภทประกาศ หากคุณหมายถึงมี::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
สิ่งที่ฉันเสนอไม่ใช่วิธีแก้ปัญหาสำหรับคำถามของคุณ แต่ฉันคิดว่ามันมีประโยชน์สำหรับฉันดังนั้นฉันจึงคิดที่จะแบ่งปัน
แก้ไข
รหัสข้างต้นยอมรับf
ได้Function
เพียง โดยทั่วไปคุณสามารถมีประเภทที่สามารถโทรได้ จากนั้นcheck_declared(m::Module, f::Function)
ลายเซ็นสามารถเปลี่ยนเป็นcheck_declared(m::Module, f)
(จริง ๆ แล้วฟังก์ชันจะอนุญาตให้Any
เป็นอาร์กิวเมนต์ที่สอง :)) และส่งชื่อที่ประเมินทั้งหมดไปยังฟังก์ชันนี้ จากนั้นคุณจะต้องตรวจสอบว่าmethods(f)
มีผลบวกlength
ภายในฟังก์ชั่น (เช่นเดียวmethods
กับที่ไม่สามารถเรียกคืนได้ค่าที่มีความยาว0
)
hasmethod(f, (Any,) )
จะกลับมาfalse
หากไม่มีคำจำกัดความทั่วไป คุณยังคงต้องตรงกับจำนวนอาร์กิวเมนต์ (เช่นhasmethod(f, (Any,Any) )
สำหรับฟังก์ชันสองอาร์กิวเมนต์)