2

相互に使用するモジュールを処理する最良の方法は何ですか?

ハッシュの関数を持つモジュールがあるとしましょう:

# Really::Useful::Functions::On::Hash.pm

use base qw<Exporter>;
use strict;
use warnings;

use Really::Useful::Functions::On::List qw<transform_list>;

our @EXPORT_OK = qw<transform_hash transform_hash_as_list ...>;

#...
sub transform_hash { ... }

#...
sub transform_hash_as_list {
    return transform_list( %{ shift() } );
}
#...
1

また、リスト用に別のモジュールが分割されています。

# Really::Useful::Functions::On::List.pm

use base qw<Exporter>;
use strict;
use warnings;

use Really::Useful::Functions::On::Hash qw<transform_hash>;

our @EXPORT_OK = qw<transform_list some_func ...>;

#...
sub transform_list { ... }

#...
sub some_func { 
    my %params = transform_hash @_;
    #...
}

#...
1

これらのユーティリティ関数が十分に便利で、BEGIN ステートメントやインポート関数で使用してパラメーター リストや構成データを処理したいとします。

サブ定義を BEGIN ブロックに入れ、誰かがモジュールをインクルードするたびに使用できるようにしています。しかし、BEGIN ブロックで定義が完了していない毛むくじゃらの競合状態に陥ってしまいました。

私は進化するコードのイディオムをモジュールに入れ、コードを何度も何度もコーディングしているイディオムを再利用できるようにしています。例えば:

sub list_if { 
    my $condition = shift;
    return unless $condition;
    my $more_args = scalar @_;
    my $arg_list  = @_ > 1 ? \@_ : @_ ? shift : $condition;
    if (( reftype( $arg_list ) || '' ) eq 'ARRAY' ) { 
        return wantarray ? @$arg_list : $arg_list;
    }
    elsif ( $more_args ) { 
        return $arg_list;
    }
    return; 
}

タイプするのにちょっとうんざりしている 2 つのイディオムをキャプチャします。

@{ func_I_hope_returns_a_listref() || [] }

( $condition ? LIST : ())

BEGIN ブロックで関数を定義すればするほど、これらのイディオム ブリックを使用してロジックを表現する可能性が高くなり、BEGIN ブロックでブリックが必要になる可能性が高くなります。

人々は、この種の言語イディオム ブリック モデルを扱う標準的な方法を持っていますか?

私は主に Pure-Perl を使ってきました。XSはこれをいくらか緩和しますか?

4

3 に答える 3

5

相互に依存するモジュールが必要な場合、その機能を実現する簡単な方法は、完全修飾名を使用した遅延バインディングサブルーチン呼び出しを使用することです(つまり、サブ呼び出しでパラメーターを使用します)。プロトタイプは機能しませんが、perlは、Somepackage::mysub()実際に呼び出そうとするまで、定義されていないことを気にしません。相互に依存するモジュールを作成するときは、通常、それらを同じファイルに保持します。これにより、インポートを完全に回避して状況を簡素化できます。

sub name {...}また、これはBEGINブロックと同じであるため、BEGINブロックでサブを定義する必要はありません。BEGIN {*name = sub {...}}

于 2010-06-16T16:50:37.463 に答える
3

これらの呼び出しは実行時に行われ、それまでに「すべて」がロードされているため、それぞれが他のモジュールを呼び出す 2 つのモジュールを持つことができます。ただし、(明らかに)これは、爆発することなくランタイムフェーズに到達する必要があることを意味します。一般的なアプローチの 1 つは、これら 2 つのいずれかよりも前に、他のモジュールを含めることuseです。direct ステートメントを削除した直接的な結果として、useこれらのインポートは失われますが、あるモジュールから別のモジュールにシンボルをインポートするのはあまり良い考えではありません。

あなたが書いたコードを見ると、データを処理するための非常に多くの「新しい」方法を思いついたので、これらを別々のライブラリに引き出す必要があることにかなり驚いています。標準ライブラリHash::UtilList::Util、およびList::MoreUtilsを見ましたか? ライブラリから離れて、標準ライブラリを使用して、より慣用的な Perlish の方法でコーディングすることをお勧めします。

于 2010-06-16T16:20:00.850 に答える
3

2 つのモジュールが相互に依存している場合、設計に何らかの問題があります。私があなただったら、モジュールのリファクタリングを考えます。

于 2010-06-16T15:37:08.827 に答える