リターンコードと例外:鐘楼からの眺め

ポストリターンコードと例外およびコメントを見て、1つのスレッドが議論に欠けていることに気付きました。その簡潔な理論は次のとおりです。一部の言語では、この問題は価値がありません。 そのような言語での質問「選択するもの、戻りコード、または除外」は低レベルです。 たとえば、「foreach」コンストラクトを実装する方法に疑問はありません。 なぜなら 同じ「foreach」を使用するプログラマにとって、作成者がこの演算子の実装でwhileを使用したか、言語または他の何かを使用したかは問題になりません。 主なものはパターンです。これはまさにこの演算子です。



foreachについて話すのをやめます。 例として、互いに非常によく似た2つの演算子を直接示します。1つは実装として「例外」を使用し、もう1つは「戻りコード」を使用します。



プロセス例外 [ マッピング本体 ]

ここで、 マッピングは{例外1 <->処理方法1、例外2 <->処理方法2、...}、body-例外が発生する可能性のある演算子の形式のマップです。



および2番目の演算子:

process-retcode-answer [ マッピングボディ ]

ここで、 マッピングは{戻りコード1 <->処理方法1、戻りコード2 <->処理方法2、...}の形式のマップです。 本文 -サブプログラムの応答で終わるステートメントの本文または必要な呼び出し先システム戻りコードに基づいたプロセス。



彼らが働くのを見てみましょう。



プロセス再コード回答





リターンコード0、-1、-2、および残りのコードを処理するロジックを処理する関数があるとします。



defn ok-processor [結果]

println str " ok。result :" result ))



defn error-processor [結果]

println str " error。result :" result ))



defn another-error-processor [結果]

println str "another error。result :" result



defn unknown-error-processor [結果]

println str "unknown error。result :" result




それらを処理する関数の名前のマップ戻りコードを定義します。



def result-mapping { 0 'ok-processor

-1 'エラープロセッサ

-2 '別のエラープロセッサ

その他の 'unknown-error-processor }





次に、さまざまな戻りコードと対応する結果を返すテストルーチンを作成します。



defn test-call-ok [ ]

[ 0 "テスト結果" ]



defn test-call- error [ ]

[ -1 "テスト結果" ]



defn test-call-another- error [ ]

[ -2 "テスト結果" ]



defn test-call-unknown- error [ ]

[ -1000 "テスト結果" ]




この場合のオペレーターの作業は次のようになります。



process-retcode-answer結果マッピング test-call-ok

わかった 結果 テスト結果



process-retcode-answer result-mapping test-call- error

エラー 結果 テスト結果



process-retcode-answer result-mapping test-call-another- error

別のエラー 結果 テスト結果



process-retcode-answer結果マッピング test-call-unknown- error

不明なエラー 結果 テスト結果




ここでは、各ボディは1つのメソッドのみで構成されています。 実際には、代わりに任意の関数シーケンスを挿入できます。



この演算子の利点は、ハンドラーを実装し、マッピングを適切に変更することにより、新しいコードの処理または既存のハンドラーの変更が透過的に実行されることです。



ifsはありません。 このアプローチは、リターンコードを処理するためのかなり柔軟なパターンを実装します。



プロセス例外





前の例との類推によって。 いくつかの例外を処理するための関数があります。



defn算術例外プロセッサ[ e ]

println str "算術例外。"



defn nullpointer-exception-processor [ e ]

println str "Nullpointer exception。"



defn another-exception-processor [ e ]

println str "その他の例外。"




それらを処理する関数の名前の例外をマップします。



def exception-mapping { java。lang。ArithmeticException 'arithmetic-exception-processor

java lang NullPointerException 'nullpointer-exception-processor

java lang 例外 'another-exception-processor }




さまざまな例外を生成するテストルーチンを作成します。



defn test-call-ok [ ]

「テスト結果」



defn test-throw-arithmetic-exception [ ]

throw new java。lang。ArithmeticException

「テスト結果」



defn test-throw-nullpointer-exception [ ]

throw 新しいjava。lang。NullPointerException

「テスト結果」



defn test-throw-other-exception [ ]

throw 新しいjava。lang。ClassNotFoundException

「テスト結果」




オペレーターの仕事:



プロセス例外の例外マッピング

test-call-ok ))

「テスト結果」



プロセス例外の例外マッピング

test-throw-arithmetic-exception

算術例外



プロセス例外の例外マッピング

test-throw-nullpointer-exception

ヌルポインター例外



プロセス例外の例外マッピング

test-throw-other-exception

その他の例外




前のステートメントの説明の最後にある注意がここに適用されます。



結論





これらの演算子は非常に似ており、原則として、同じ応答処理パターンを実装しますが、実装は異なります。 ここでは、 process-retcode-answerを優先します 。 他の言語では、例外を使用するバリアントと比較して、リターンコードを持つバリアントが常に有利であるとは限りません(もちろん、問題の条件と言語自体に依存します-これについては既に説明しました)。



上記の演算子の実装オプションは次のとおりです。



defmacroプロセス例外[マッピング本体]

let [ catch-items map fn [ m ]

` catch〜 first m e#

eval second m e#

eval mapping ]

` try〜@ body

〜@ catch-items




defmacro process-retcode-answer [ mapping body ]

` let [ answer# do〜@ body

retcode# 最初の回答#

結果# 2番目の回答#

プロセッサー# get〜マッピングretcode#

プロセッサ# if nil ?processor# other〜mapping プロセッサ# ]

eval processor# result#




このかなり誇張された例は、新しいコンストラクトで言語を拡張し、同じ高次関数、ラムダ、クロージャーを持つ機能のように、言語の基本要素はあまり重要ではないことを示しています。 このような言語により、プログラマーはアーティストになれます。 彼は何度も何度もパターンを書きません。 彼は、自分の仕事の解決策を最も自然に、グラフィカルに、簡潔に定式化できる言語を単に「作成」します。 職業は工芸ではなく芸術になります。



All Articles