4

私はむしろこれをしたい:

say $shop->ShopperDueDate->andand->day_name();

対これ:

say $shop->ShopperDueDate->day_name() if $shop->ShopperDueDate;

何か案は?

(このアイデアは、Ruby のandand拡張機能に触発されています。)

(実際にはGroovy言語にインスパイアされていますが、ほとんどの人はそれを知りません;-)

update : Maybe() と eval {} の両方が良い解決策だと思います。これはルビーではないので、すべてのメソッド/関数を左から右に読むことは期待できないので、おそらく助けになるでしょう。そしてもちろん、eval は実際にそれを行う perl の方法です。

4

4 に答える 4

9

Perlのevalステートメントを使用して、未定義の引数でメソッドを呼び出そうとする例外を含む例外をキャッチできます。

eval {
    say $shop->ShopperDueDate->day_name();
};

eval評価された最後のステートメントが返されるため、または失敗undefした場合は、次のような変数に曜日名を記録できます。

my $day_name = eval { $shop->ShopperDueDate->day_name(); };

実際に例外を検査したい場合は、特別な変数を調べることができます$@これは通常、Perlの組み込み例外の単純な文字列ですが、例外がautodieまたはオブジェクト例外を使用する他のコードから発生した場合は、完全な例外オブジェクトになる可能性があります。

eval {
    say $shop->ShopperDueDate->day_name();
};

if ($@) {
    say "The error was: $@";
}

evalブロックを使用して一連のコマンドをつなぎ合わせることができます。以下は、検索時に例外がスローされていない場合にのみ、週末かどうかを確認します$day_name

eval {
    my $day_name = $shop->ShopperDueDate->day_name();

    if ($day_name ~~ [ 'Saturday', 'Sunday' ] ) {
        say "I like weekends";
    }
};

他の言語evalと同じであると考えることができます。try実際、CPANのErrorモジュールを使用している場合は、それを綴ることもできますtry。また、evalのブロック形式(上記で説明しました)にはパフォーマンスのペナルティがなく、残りのコードと一緒にコンパイルされることにも注意してください。の文字列形式eval(私は示していません)はまったく別の獣であり、使用する場合は控えめに使用する必要があります。

eval技術的にはPerlのステートメントと見なされているため、ブロックの最後にセミコロンが表示される数少ない場所の1つです。eval定期的に使用しないと、これらを忘れがちです。

ポール

于 2009-01-08T01:32:06.337 に答える
9

2番目の例は次のようにすると思います。

say $shop->ShopperDueDate ? $shop->ShopperDueDate->day_name() : undef;

それが実際に言うことの代わりに。

とにかく、はオブジェクトではなく単項演算子であるため、ソースフィルタなしでその構文を正確に実行することはできません。したがって、メソッドを持つことはできません。undef

代わりに、これを考慮してください:

package noop; 
our $maybe = bless [], 'noop';
sub AUTOLOAD { undef };

これ$noop::maybeはオブジェクトです。ただし、そのすべてのメソッドが返さundefれます。他の場所では、次のような通常の関数があります。

sub maybe { $_[0] || $noop::maybe; }

次に、これを書くことができます:

say maybe($shop->ShopperDueDate)->day_name()

これが機能するのは、「たぶん」がtrueの場合に引数を返す場合、それ以外の場合は$noop::maybe常にundefを返すメソッドを持つオブジェクトを返すためです。

編集:訂正!->andand->構文は、Perlの内部をいじくり回すXSを使用することにより、ソースフィルターなしで使用できます。Leon Timmermansは、このルートを採用した実装を作成しました。これは関数をグローバルに置き換えるため、私の方法よりもはるかに遅くなる可能性があります。undef()

于 2009-01-08T01:32:36.697 に答える
4

書いたばかりだと思います。私はそれを CPAN にアップロードしました。ここで見つけることができます。

于 2009-01-08T16:25:07.673 に答える
0

(未テスト) のようなもの:

use Object::Generic::False;
sub UNIVERSAL::andand { $_[0] || Object::Generic::False->false }

UNIVERSAL は自動的に他のすべてのクラスのサブクラスになるため、すべてのオブジェクトに andand が提供されます。(明らかに、UNIVERSAL でメソッドを作成すると、競合が発生したり、離れた場所で予期しないアクションが発生したりする可能性があるため、不注意に使用しないでください。) andand メソッドが呼び出されたオブジェクトが true の場合は、それを返します。それ以外の場合は、使用されたメソッド呼び出しに対してそれ自体を返す一般的な false オブジェクトを返します。

于 2009-01-08T06:03:09.130 に答える