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

ポストリターンコードと例外およびコメントを見て、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