2016-08-09 6 views
4

perlには、useステートメントに関数名を指定する必要があることがあります。例えばuse文で関数名を指定する必要があるのはなぜですか?

use Data::DPath ('dpath'); 

動作しますが、

use Data::DPath; 

はしません。

他のモジュールは、たとえば、指定された関数名を必要としない:

use WWW::Mechanize; 

なぜ?

+0

名前で関数を使用せずに関数を使用する特定の 'WWW :: Mechanize'の例がありますか? [MCVE](http://stackoverflow.com/help/mcve)を投稿できますか? – ray

+0

@ray 'use WWW :: Mechanize; my $ mech =新しいWWW :: Mechanize; $ mech-> get( "http://www.google.com"); ' – CJ7

+0

' $ mech-> get(...) 'は単なるインスタンスメソッドを呼び出すオブジェクトなので、実際は同じではありません。 – ray

答えて

1

一部のモジュールには単に関数が含まれているため、デフォルトでエクスポートするかどうかを選択していない場合があります。つまり、直接アクセスするためにスクリプトによって明示的にインポートする必要があります。それらにアクセスするための名前。例えば:

# in some script 
use SomeModule; 
# ... 
SomeModule::some_function(...); 

又は

use SomeModule ('some_function'); 
# ... 
some_function(...); 

これは、モジュールは、オブジェクト指向の方法で使用するためのものでなかった場合、すなわち、何のクラスが定義されていないとのような線ようなされている場合であってもよいですmy $obj = SomeModule->new()は機能しません。

EXPORT_OK配列のコンテンツがモジュールに定義されている場合、実際にEXPORT配列に存在する場合、クライアントコードは「自動的に」要求するのではなく、「要求する」場合にのみアクセスします。

一部のモジュールは、@EXPORTアレイを使用してコンテンツを自動的に書き出します。 This questionおよびExporter docsにこれ以上の詳細があります。

あなたが実際にMCVEを掲示しないと、それはあなたがEXPORTEXPORT_OK配列を使用せずに、すべてをインポートできるようにすることができるあなたのFuncs.pmモジュールに何をやったかを知ることは困難です。 @JonathanLefflerがコメントに示唆したように、おそらくあなたはあなたのモジュールにpackage Funcs;行を含めなかったでしょう。多分あなたは何か他のことをしました。 Perlは人々がTMTOWTDIマントラに誇りを持ち、しばしば有害/反生産的なレベルのIMHOに誇りを持つ言語の1つです。

あなたが提示した2番目の例は、非常に異なり、かなり簡単です。

use WWW::Mechanize; 
my $mech = new WWW::Mechanize; 
$mech->get("http://www.google.com"); 

は、あなたは、単にタイプWWW::Mechanizeのオブジェクトをインスタンス化し、その上に、getというインスタンスメソッドを、呼び出している:あなたのような何かを持っている場合。メソッドがオブジェクトの一部であるため、オブジェクトのメソッドをインポートする必要はありません。 OOPアプローチをとっているモジュールは何もエクスポートするものではありません。彼らは別の状況です。

9

各モジュールは、デフォルトでどの機能をエクスポートするかを選択します。何人かは、デフォルトではの機能を全くエクスポートしないように選択する必要があります。これにはいくつかの理由があり、一つは悪いことです。

クラスがWWW::Mechanizeの場合は、関数をエクスポートする必要はありません。すべてがクラスまたはオブジェクトメソッドです。 my $mech = WWW::Mechanize->new

プラグマの場合、strictのような機能や方法はありませんが、ロードするだけで作業はできます。

一部のモジュールはデフォルトであまりにも多くの関数をエクスポートします。例は

すべての任意の配列BOOL cmp_bag cmp_deeply cmp_methods cmp_setコードeq_deeply hashkeysonlyイサのISA listmethods方法noclass どれを無視しない hash_eachのHASHKEYSをハッシュnoneof NUM obj_isa再reftype regexpmatches祝福arraylengthonlyバッグにarrayLength arrayelementsonly array_each ...エクスポートTest::Deepありますregexponly regexpref がregexprefonly scalarrefonly設定scalref浅いSTR subbagof subhashof subsetof superbagof superhashof supersetof useclass

問題が来たときに、別のMODU同じ関数をエクスポートしようとした場合、または同じ名前の関数を記述した場合。それから彼らは衝突し、神秘的な警告を得る。

$ cat ~/tmp/test.plx 
use Test::Deep; 
use List::Util qw(all); 

$ perl -w ~/tmp/test.plx 
Subroutine main::all redefined at /Users/schwern/perl5/perlbrew/perls/perl-5.20.2/lib/5.20.2/Exporter.pm line 66. 
at /Users/schwern/tmp/test.plx line 2. 
Prototype mismatch: sub main::all: none vs (&@) at /Users/schwern/perl5/perlbrew/perls/perl-5.20.2/lib/5.20.2/Exporter.pm line 66. 
at /Users/schwern/tmp/test.plx line 2. 

このため、多くの機能をエクスポートすることはお勧めしません。たとえば、the Exporter documentation advises ...

メソッド名をエクスポートしないでください。

正当な理由がなければ、デフォルトで他のものをエクスポートしないでください!

エクスポートは、モジュールユーザーの名前空間を汚染します。エクスポートする必要がある場合は、@ EXPORTに優先して@EXPORT_OKを使用し、名前の衝突の危険性を減らすために、短い記号または共通の記号名を避けてください。

残念ながら、残念ながら、一部のモジュールでこれを行うにはあまりにも時間がかかります。 Data::DPathが良い例です。それは本当に明確なメイン関数dpath()を持っています。これはデフォルトでエクスポートする必要があります。さもなければ、それは基本的に役に立たない。

use Some::Module();でいつでもエクスポートをオフにすることができます。

+0

私は自分自身の 'Funcs.pm'ファイルを持っています。関数をインポートするためには 'use Funcs;'が必要です。 'Funcs.pm'ファイルには単に関数が含まれていて、' @ EXPORT_OK'のどこにも言及されていません。 – CJ7

+3

@ CJ7あなたはFuncs.pmにパッケージ名を入れていないと思いますので、すべてデフォルトのパッケージである 'main'に入っています。これは非常に無礼です。 Funcs.pmがFuncsパッケージを使用し、他のパッケージを汚染しないようにするための非常に強力な規則です。 – Schwern

+1

@ CJ7:おそらく、あなたのファイルにパッケージ表記がないので、すべてが自動的に利用可能になりますグローバルな名前空間で。あなたはそれを行うことができます - それは動作します。しかし、正式なモジュール( 'WWW :: Mechanize'など)はパッケージの表記法を使って内部構造を公開しないようにしており、適切に管理されたモジュールは最小限の必要な名前やユーザー指定のリストをエクスポートするだけです。名前空間の不要な汚染を防ぎます。 –

関連する問題