2016-09-18 47 views
2

有兩個包我想用:CorpusLoaders.jlWordNet.jl兩個模塊,這兩個出口同名

  • CorpusLoaders.SemCor出口sensekey(::SenseTaggedWord)
  • 共發現出口sensekey(::DB, ::Synset, ::Lemma)

我想同時使用sensekey方法。

的項目的一些混合列表:mixedlist::Vector{Union{Tuple{SenseTaggedWord},Tuple{DB, Synset,Lemma}}。即,列表中的項目是SenseTaggedWord的1元組和DB,SynsetLemma的3元組的混合。

for item in mixedlist 
    println(sensekey(item...) 
end 

應該工作。 這個例子有點兒滑稽,因爲我爲什麼要像這樣混合它們。 但是,希望它可以解釋一般情況下的問題。

試圖using CorpusLoaders.SemCor, WordNet帶來兩個結果WARNING: both WordNet and Semcor export "sensekey"; uses of it in module Main must be qualified.

手動導入兩種:import CorpusLoaders.SemCor.sensekey; import WordNet.sensekey結果WARNING: ignoring conflicting import of Semcor.sensekey into Main

可以做些什麼?我希望他們兩個,而且他們並沒有真正的衝突,由於多派遣。


鑑於CorpusLoaders.jl是一個包,我寫我確實有一些更多的選擇,因爲我可以讓我的CorpusLoaders.jl取決於WordNet.jl。 如果我不是那麼做,我可以在CorpusLoaders.jl

import WordNet 
function WordNet.sensekey(s::SenseTaggedWord)... 

說這將讓他們都工作。 但這意味着需要WordNet作爲CorpusLoaders的依賴。

我想知道如何解決包裝的消費者的問題 - 而不是包裝的創造者。

+1

不管怎樣,離開它,我的答案主要是關於用戶案例。希望有相同問題的人需要比馮洋的答案更詳細一點(或*很多*:p)的細節,那麼下面就會碰到我的問題:D我只是想將我的意見轉換成將他們從這裏刪除的答案,heheh。我會刪除上面的評論洪流:p 感謝您花時間編輯/澄清! –

回答

5

在這種情況下,該功能不衝突,但一般是無法保證。可能會出現這樣的情況,稍後加載的程序包會將方法添加到會衝突的某個函數中。因此,要將sensekey用於這兩個包,需要一些額外的保證和限制。要做到這一點

一種方式是忽略這兩個包的sensekey,而是提供自己,派遣到正確的包:

sensekey(x) = CorpusLoaders.sensekey(x) 
sensekey(x, y, z) = WordNet.sensekey(x,y,z) 
4

我實現@Fengyang小王說什麼, 作爲一個函數:

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) 

2方法通用函數sensekey:

  • sensekey(分貝:: WordNet.DB,SS :: WordNet.Synset,LEM :: WordNet.Lemma)
  • sensekey(saword :: CorpusLoaders.Semcor .SenseAnnatedatedWord

如果您想真正使用Flash,則可以重新導出DocString。

4

TL;通過他們的模塊命名空間在腳本中使用它們的時候,即CorpusLoader.sensekey()WordNet.sensekey()


解釋博士限定功能

我的編輯後,你的問題的理解(謝謝澄清)是這樣的:

  • 你已經寫了一個叫做CorpusLoaders.jl,其中出口功能sensekey(::SenseTaggedWord)
  • 有一個外部的軟件包叫做WordNet.jl,其中出口功能sensekey(::DB, ::Synset, ::Lemma)
  • 你有一個腳本,利用這兩個模塊。

和你擔心using模塊或「進口」的功能直接可能建立在你的腳本不確定性和/或錯誤,要求

  1. 我怎麼能寫我的CorpusLoaders包,以防止可能與其他軟件包發生衝突,並且
  2. 如何在寫入腳本時明確區分這兩個函數並同時允許它們使用?

我想從一個輕微的混亂這源於如何usingimport彼此不同,和模塊如何創建一個命名空間。這在文檔here中有很好的解釋。

從本質上說,答案是:

  1. 你不應該擔心出口從模塊的東西,將與其他模塊衝突。這是模塊的用途:您正在創建一個命名空間,它將「限定」所有導出的變量,例如CorpusLoaders.sensekey(::SenseTaggedWord)

  2. 當你鍵入using CorpusLoaders,你的意思朱莉婭是「進口模塊本身,都從他們的命名空間預選賽剝離導出的變量,並將其納入主」。請注意,這意味着您現在可以直接使用sensekey作爲不帶名稱空間限定符的主函數作爲CorpusLoaders.sensekey(),因爲您也已將模塊導入爲可用的變量。

如果再嘗試using模塊WordNet以及朱莉婭非常合理發出警告,基本上說:

「你已經導入了具有相同名稱的兩個功能,我可以不要把它們的名字空間去掉,因爲這可能會在某些場景中產生問題(即使在你的情況下,它不會因爲它們具有不同的簽名,但我通常不可能知道這一點)如果你想使用這些函數,請使用其適當的名稱空間限定符「。

因此,對於2解決辦法是:

  • 你要麼做

    using CorpusLoaders; 
    using WordNet; 
    

    ,不顧警告,導入所有其他出口變量像往常一樣在你的主命名空間,並通過它們的模塊直接訪問這些特定功能,如CorpusLoaders.sensekey()WordNet.sensekey()每次需要在您的腳本中使用它們,或者

  • 你做

    import CorpusLoaders; 
    import WordNet; 
    

    始終保持清晰地消除歧義的兩個模塊和資格所有變量爲正確,或

  • 在這種特定情況下的函數簽名不衝突,如果你'd 真的喜歡能夠使用沒有命名空間限定符的功能,而是依靠多次調度來代替,你可以做些什麼像馮洋建議的那樣:

    import CorpusLoaders; 
    import WordNet; 
    sensekey(a::SenseTaggedWord) = CorpusLoader.sensekey(a); 
    sensekey(a::DB, b::Synset, c::Lemma) = WordNet.sensekey(a, b, c); 
    

    其實質上是函數,在模塊Main上定義,充當兩個命名空間限定函數的包裝。

最後,這一切歸結爲使用using VS import和命名空間適當地爲您的特定代碼。 :)


作爲附錄,代碼可能會變得非常難以使用長名稱空間限定符如 CorpusLoaderWordNet。julia沒有類似python的 import numpy as np, ,但在同一時間模塊成爲您的工作區上的簡單變量,所以這是微不足道的爲他們創建一個別名。所以你可以這樣做:

import CorpusLoaders; const cl = CorpusLoaders; 
import Wordnet;  const wn = WordNet; 
# ... code using both cl.sensekey() and wn.sensekey()