2016-09-18 4 views
2

2つの、私が使用したいパッケージがあります:CorpusLoaders.jl、およびWordNet.jl2つのモジュールの両方に同じ名前をエクスポート

  • CorpusLoaders.SemCor輸出sensekey(::SenseTaggedWord)
  • WordNetの輸出sensekey(::DB, ::Synset, ::Lemma)

は私がしたいです両方の方法を使用してください。項目のいくつかの混合リスト用など

mixedlist::Vector{Union{Tuple{SenseTaggedWord},Tuple{DB, Synset,Lemma}}。 リストの項目は、SenseTaggedWordの1タプルとDBSynset、およびLemmaの3つのタプルの混合物です。

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

が有効です。 この例は少し面白いです。 しかし、うまくいけば、それは一般的な場合の問題を説明するのに役立ちます。

手動の両方をインポートWARNING: both WordNet and Semcor export "sensekey"; uses of it in module Main must be qualified.

で両方の結果をもたらすことusing CorpusLoaders.SemCor, WordNetしようとしている:WARNING: ignoring conflicting import of Semcor.sensekey into Main

import CorpusLoaders.SemCor.sensekey; import WordNet.sensekey結果をどのように行うことができますか?私はそれらを両方とも望んでおり、複数のディスパッチのために実際には衝突しません。


CorpusLoaders.jlは私が私のCorpusLoaders.jlがWordNet.jlに依存させる可能性があるため、私は、いくつかのより多くのオプションを持っているん書いていますパッケージであることを考えます。 私はその後、よりやったのなら、私はCorpusLoaders.jl

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

に言うことができる、それはそれらの両方の仕事になるだろう。 しかし、WordNetにはCorpusLoadersの依存関係が必要です。

そして、パッケージの作成者ではなく、パッケージの消費者の問題を解決する方法を知りたいと思います。

+1

nah、私の答えは、とにかくユーザーの場合についてです。幸運なことに、FengYangの答えよりも細かい(または* lot *:p)詳細が必要な同じ質問をした人は、次に私のものにぶつかります。Dここでコメントを答えに移して、hehehから取り除きたいと思っています。上記のコメントのトレントを削除します:p 編集/明解に時間を割いてくれてありがとう! –

答えて

5

この場合、機能は競合しませんが、一般的に保証することはできません。後で読み込まれたパッケージが、競合する関数の1つにメソッドを追加する場合があります。したがって、両方のパッケージにsensekeyを使用できるようにするには、いくつかの追加の保証と制限が必要です。

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

私が実装@Fengyang王が言ったことを、関数として ::これを行うには

一つの方法は、正しいパッケージに派遣し、両方のパッケージのsensekeyを無視し、代わりに自分自身を提供することであり

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(DB :: WordNet.DB、SS :: WordNet.Synset、LEM :: WordNet.Lemma)
  • sensekey(saword :: CorpusLoaders.Semcor .SenseAnnotatedWord

実際にフラッシュしたい場合は、DocStringも再エクスポートすることができます。

4

TL;すなわち、そのモジュールの名前空間を経由して、あなたのスクリプトでCorpusLoader.sensekey()WordNet.sensekey()


説明をそれらを使用する場合、DR

編集後のあなたの質問の私の理解で(機能を修飾明確化のためにありがとうございます)は次のとおりです。

  • あなたは機能sensekey(::DB, ::Synset, ::Lemma)
  • あなたは両方のモジュールを使用するスクリプトを持っているをエクスポートWordNet.jlという外部パッケージは、ある機能sensekey(::SenseTaggedWord)
  • にエクスポートCorpusLoaders.jlというパッケージを、書かれています。

、あなたはusingモジュールや関数を直接「インポート」は潜在的に、私は可能性を防ぐために、私のCorpusLoadersパッケージを書くことができますどのように

  1. を求めて、スクリプトの中で曖昧かつ/またはエラーを作成することができることを心配しています他のパッケージとの衝突、および
  2. 2つの機能を明確に区別して使用するにはどうすればよいですか?

私は、これはわずかusingimportが互いに異なっているかの混乱、そしてどのようにモジュールは、名前空間を作成由来だと思います。これはドキュメントhereで非常にうまく説明されています。

は本質的には、答えがある:あなたが他のモジュールと衝突しますあなたのモジュールから物事をエクスポート心配してはいけません

  1. 。これは、モジュールのためのものです。名前空間を作成しています。名前空間は、エクスポートされたすべての変数を「修飾」します。 CorpusLoaders.sensekey(::SenseTaggedWord)

  2. あなたがusing CorpusLoadersを入力すると、あなたがジュリアに言っていること「その名前空間修飾子から取り除かエクスポートされたすべての変数をモジュール自体をインポートし、そしてメインにそれらをもたらす」です。これは、あなたがモジュールを変数としてインポートしたので、sensekeyが名前空間修飾子なしでMainから直接関数としてCorpusLoaders.sensekey()としてアクセスできることに注意してください。

あなたは、その後、同様usingモジュールWordNetをしようとすると、ジュリアは非常に合理的に、本質的に言う警告、発行:

「あなたは、同じ名前を持つ2つの関数をインポートした私ができるの。自分の名前空間を取り除くのは、いくつかのシナリオで問題を引き起こす可能性があるからです(あなたのケースでは署名が違うからではありませんが、一般的にこれを知ることはできません)。これらの関数は、適切な名前空間修飾子を使用してください。 "

ので、2のためのソリューションです:

  • あなたは、自分のメインの名前空間でいつものように他のすべてのエクスポートされた変数をインポートするには、警告を無視し、

    using CorpusLoaders; 
    using WordNet; 
    

    を行うのいずれかスクリプト内で使用するたびにCorpusLoaders.sensekey()WordNet.sensekey()というモジュールを介してこれらの特定の関数に直接アクセスするか、

  • あなたがあれば、関数のシグネチャが衝突しないこの特定のケースではすべて適切変数、または

  • import CorpusLoaders; 
    import WordNet; 
    

    を行うことによって明確にすべての回で明確化の両方のモジュールを維持し、資格'd 実際には、代わりに複数のディスパッチに頼って、名前空間修飾子なしで関数を使用できるようにしています.FengYangが示唆したような何かをすることができます:

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

    基本的に2つの名前空間修飾機能のラッパーとして動作するモジュールメインに定義された新しい機能、です。最後に

、それはすべてあなたの特定のコードのために適切に usingimportと名前空間を使用してダウンしています。 :)
補足として、 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() 
関連する問題