Module 两个模块,都导出相同的名称
我想使用两个包:,和Module 两个模块,都导出相同的名称,module,packages,julia,Module,Packages,Julia,我想使用两个包:,和 微粒装载机.SemCor导出sensekey(::SenseTaggedWord) WordNet导出sensekey(::DB,::Synset,::Lemma) 我想使用这两种sensekey方法 乙二醇 对于一些混合项列表:mixedlist::Vector{Union{Tuple{SenseTaggedWord},Tuple{DB,Synset,Lemma}。 即列表中的项目由1个元组的sensetagedword和3个元组的DB、Synset和Lemma组成
- 微粒装载机.SemCor导出
sensekey(::SenseTaggedWord)
- WordNet导出sensekey(::DB,::Synset,::Lemma)
sensekey
方法
乙二醇
对于一些混合项列表:mixedlist::Vector{Union{Tuple{SenseTaggedWord},Tuple{DB,Synset,Lemma}
。
即列表中的项目由1个元组的sensetagedword
和3个元组的DB
、Synset
和Lemma
组成
for item in mixedlist
println(sensekey(item...)
end
应该有用。
这个例子有点滑稽,因为我为什么要这样混合它们。
但是,希望它能说明一般情况下的问题
试图使用CorpusLoaders.SemCor、WordNet
在警告中引入这两个结果:WordNet和SemCor都导出“sensekey”;在模块Main中使用它必须是合格的。
手动导入这两者:import-CorpusLoaders.SemCor.sensekey;import-WordNet.sensekey
将导致警告:忽略将SemCor.sensekey导入Main的冲突
可以做什么?我想要两者,而且它们不会因为多次调度而发生冲突。
鉴于CorpusLoaders.jl是我正在编写的一个包,我还有一些选择,因为我可以让我的CorpusLoaders.jl依赖于WordNet.jl。 如果我做了,那么我可以在CorpusLoaders.jl中说
import WordNet
function WordNet.sensekey(s::SenseTaggedWord)...
这将使它们都起作用。
但这意味着需要WordNet作为微粒装载机的依赖项
我想知道如何为软件包的消费者解决这个问题,而不是作为软件包的创建者
在这种情况下,函数不会发生冲突,但通常这是无法保证的。可能是以后加载的包会向其中一个函数添加将发生冲突的方法。因此,要对两个包都使用
sensekey
,需要一些额外的保证和限制
一种方法是忽略两个包的sensekey
,而是提供您自己的,发送到正确的包:
sensekey(x) = CorpusLoaders.sensekey(x)
sensekey(x, y, z) = WordNet.sensekey(x,y,z)
我实现了@Fengyang Wang所说的, 作为一项功能:
function importfrom(moduleinstance::Module, functionname::Symbol, argtypes::Tuple)
meths = methods(moduleinstance.(functionname), argtypes)
importfrom(moduleinstance, functionname, meths)
end
function importfrom(moduleinstance::Module, functionname::Symbol)
meths = methods(moduleinstance.(functionname))
importfrom(moduleinstance, functionname, meths)
end
function importfrom(moduleinstance::Module, functionname::Symbol, meths::Base.MethodList)
for mt in meths
paramnames = collect(mt.lambda_template.slotnames[2:end])
paramtypes = collect(mt.sig.parameters[2:end])
paramsig = ((n,t)->Expr(:(::),n,t)).(paramnames, paramtypes)
funcdec = Expr(:(=),
Expr(:call, functionname, paramsig...),
Expr(:call, :($moduleinstance.$functionname), paramnames...)
)
current_module().eval(funcdec) #Runs at global scope, from calling module
end
end
致电:
using WordNet
using CorpusLoaders.Semcor
importfrom(CorpusLoaders.Semcor, :sensekey)
importfrom(WordNet, :sensekey)
methods(sensekey)
通用函数sensekey的两种方法:
- sensekey(db::WordNet.db,ss::WordNet.Synset,lem::WordNet.Lemma)
- sensekey(saword::微粒装载机.Semcor.SenseAnnotatedWord)
如果你想得到真正的flash,你也可以重新导出DocString。tl;dr在脚本中使用函数时,通过它们的模块名称空间,即
CorpusLoader.sensekey()
和WordNet.sensekey()
解释 我在编辑后对您的问题的理解(感谢您的澄清)是:
- 您已经编写了一个名为
的包,它导出函数CorpusLoaders.jl
sensekey(::SenseTaggedWord)
- 有一个名为
的外部包,它导出函数WordNet.jl
sensekey(::DB,::Synset,::Lemma)
- 您有一个使用这两个模块的脚本
使用模块或直接“导入”函数可能会在脚本中产生歧义和/或错误
如何编写我的CorpusLoaders
包以防止与其他包发生潜在冲突,以及
我如何编写脚本来清楚地消除这两个函数之间的歧义,同时仍然允许使用它们
我认为这源于对使用
和导入
之间的区别,以及模块如何创建名称空间的轻微混淆。这在文档中有很好的解释
基本上,答案是:
您不必担心从模块中导出会与其他模块冲突的内容。这就是模块的用途:您正在创建一个名称空间,该名称空间将“限定”所有导出的变量,例如CorpusLoaders.sensekey(::SenseTaggedWord)
当您使用微粒加载器键入时,您要对julia说的是“导入模块本身,以及从名称空间限定符中剥离出来的所有导出变量,并将它们带到Main中”。请注意,这意味着您现在可以直接从Main以函数的形式访问sensekey
,而无需名称空间限定符,也可以作为CorpusLoaders.sensekey()
,因为您还将模块作为可使用的变量导入
如果您随后尝试使用模块WordNet
,julia会非常合理地发出警告,其实质是:
“您导入了两个同名的函数。我不能只删除它们的命名空间,因为这可能会在某些情况下产生问题(即使在您的情况下不会,因为它们具有不同的签名,但我一般不可能知道这一点)。如果要使用这些函数中的任何一个,请使用其相应的命名空间限定符”
因此,2.的解决方案是:
- 你也可以
using CorpusLoaders;
using WordNet;
,忽略警告,像往常一样在主命名空间中导入所有其他导出的变量,并在每次需要在脚本中使用它们时,通过其模块直接访问这些特定函数,如CorpusLoaders.sensekey()
和WordNet.sensekey()
,或者
- 通过这样做,您可以始终清楚地消除两个模块之间的歧义
import CorpusLoaders;
import WordNet;
并适当地限定所有变量,或
- 在函数签名不冲突的特定情况下,如果您真的希望能够在不使用名称空间限定符的情况下使用函数,而是依赖于多个分派,那么您可以执行类似FengYang建议的操作:
import CorpusLoaders;
import WordNet;
sensekey(a::SenseTaggedWord) = CorpusLoader.sensekey(a);
sensekey(a::DB, b::Synset, c::Lemma) = WordNet.sensekey(a, b, c);
这本质上是一个import CorpusLoaders; const cl = CorpusLoaders;
import Wordnet; const wn = WordNet;
# ... code using both cl.sensekey() and wn.sensekey()