0

commit() と rollback() を自動的にサポートする API を構築しようとしています。調査の結果、使用することが最善の方法であることがわかりましたeval {}

eval {}をすべきかを知るために、API に関数の配列を与えることを考えました。これはforeach、API が何も解釈しなくても実行できます。ただし、この関数は別のパッケージに含まれている場合があります。

例を挙げて明確にしましょう:

sub handler {
    use OSA::SQL;
    use OSA::ourAPI;
    my @functions = ();
    push(@functions, OSA::SQL->add_page($date, $stuff, $foo, $bar));
    my $API = OSA::ourAPI->connect();
    $API->exec_multi(@functions);
}

問題は、API に がなくても、@functions内で関数を実行できるかどうかです。そうでない場合、ポインターがメモリ内の既知の関数を指すことを考えると、配列の代わりに配列参照を使用すれば可能でしょうか?OSA::ourAPIuse OSA::SQL

注: これは、より複雑な最終バージョンの基にしたい基本的な考え方です。

4

1 に答える 1

4

  • 配列に関数ポインタを追加していません。add_page() サブルーチンの呼び出しの戻り値を追加しています。これには 3 つの解決策があります。

    @functionsA.形式の arrayref の配列を( に) 格納する必要があります。これは[\&OSA::SQL::add_page, @argument_values]、(静的に呼び出される) サブルーチンへの実際の参照を渡すことを意味します。そして、 exec_multi は次のようなことを行います (ここでは午前 4 時なので、構文は 100% 正しくない可能性があります)。

    サブexec_multi {
        私の ($class, $funcs)= @_;
        foreach my $f (@$funcs) {
            私 ($func, @args) = @$f;
            私の $res = &$func(@args);
            print "RES:$res\n";
        }
    }
    

    繰り返しますが、これは静的バージョン ( OSA::SQL::add_page) の個々のサブルーチンを呼び出します。たとえば、クラス呼び出しのようにパッケージ名を最初のパラメーターとして渡すことはありOSA::SQL->add_pageません。後者が必要な場合は、次の解決策を参照してください。


    B.クラスコンテキストでサブを呼び出したい場合(例のように、つまり、クラス名を最初のパラメーターとして)、コメントでysthの提案を使用できます。

    @functions形式の arrayref の配列を( に) 格納する必要が[sub { OSA::SQL->add_page(@argument_values) }]あります。つまり、必要なものを呼び出すサブルーチンへの参照を渡します。そして、 exec_multi は次のようなことを行います (ここでは午前 4 時なので、構文は 100% 正しくない可能性があります)。

    サブexec_multi {
        私の ($class, $funcs)= @_;
        foreach my $f (@$funcs) {
            私 ($func) = @$f;
            私の $res = &$func();
            print "RES:$res\n";
        }
    }
    

    @functionsC.形式の arrayref の配列を( に) 格納する必要があります。[ "OSA::SQL", "add_page", @argument_values]つまり、パッケージ名と関数名を渡します。そして、 exec_multi は次のようなことを行います (ここでは午前 4 時なので、構文は 100% 正しくない可能性があります)。

    my ($package, $sub, @args) = @{ $functions[$i] };
    厳密な「参照」はありません。
    $package->$sub(@args);
    厳密な「参照」を使用してください。
    

  • 私があなたの質問を正しく理解していれば、私たちの API が OSA::SQL を使用しているかどうかについて心配する必要はありません。なぜなら、あなたのメイン コードは既に OSA::SQL をインポートしているためです。

    ただし、#1B では、パッケージのリストを各 arrayref の最初の要素として exec_multi に渡すので、exec_multi で " require $package; $package->import();" を実行できます。ただし、ハンドラー呼び出しが既に必要であり、これらの各パッケージをロードしている場合は、まったく必要ありません。そして、それを正しく行うには、パラメーターのリストも渡す必要がありますimport()。しかし、なぜYYYYYY? :)

于 2010-08-04T07:38:18.150 に答える