13

そのため、ユーザーがアカウント登録のリクエストを送信すると、ユーザー名、パスワード、電子メール、およびその他の情報が送信されます。登録機能は、すべてのデータを検証する必要があります。例は次のとおりです。

  • メールが使用されていないことを確認する
  • ユーザー名が使用されていないことを確認する
  • ユーザー名が英数字であることを確認します
  • すべてのフィールドの長さが X 文字を超えていることを確認します
  • すべてのフィールドの長さが Y 文字未満であることを確認します

今、私は 5 レベルの深さの if または case ステートメントを持ちたくありませんが、他にどのようなオプションがありますか? それを別々の関数に分割するのは良い考えのように思えますが、関数の戻り値をある種の条件でチェックするだけで、元の問題に戻ります。

それらを関数に分割し、すべての条件を OR で結合した if ステートメントを呼び出すこともできますが、特定のエラーがあった場合にユーザーにそのエラーを伝える必要があるため、それでは必要な結果が得られません。

erlang でこの種の状況をどのように処理しますか? return ステートメントに相当するものはありますか、それとも関数内の最後の実行可能な行である必要がありますか?

4

4 に答える 4

35

Joe Armstrong の提案の 1 つ: エラー処理から分離されたプログラム成功ケース コード。こんな感じで作れます

create_user(Email, UserName, Password) ->
  try
    ok = new_email(Email),
    ok = valid_user_name(UserName),
    ok = new_user(UserName),
    ok = strong_password(Password),
    ...
    _create_user(Email, UserName, Password)
  catch
    error:{badmatch, email_in_use} -> do_something();
    error:{badmatch, invalid_user_name} -> do_something();
    error:{badmatch, user_exists} -> do_something();
    error:{badmatch, weak_password} -> do_something();
    ...
  end.

create_user 関数からすべてのエラーキャッチを実行できることに注意してください。

create_user(Email, UserName, Password) ->
    ok = new_email(Email),
    ok = valid_user_name(UserName),
    ok = new_user(UserName),
    ok = strong_password(Password),
    ...
    _create_user(Email, UserName, Password).

main() ->
  try
    ...
    some_function_where_create_user_is_called(),
    ...
  catch
    ...
    error:{badmatch, email_in_use} -> do_something();
    error:{badmatch, invalid_user_name} -> do_something();
    error:{badmatch, user_exists} -> do_something();
    error:{badmatch, weak_password} -> do_something();
    ...
  end.

パターン マッチは、Erlang で最もクールな機能の 1 つです。タグを不正一致エラーに含めることができることに注意してください

{my_tag, ok} = {my_tag, my_call(X)}

カスタムデータも

{my_tag, ok, X} = {my_tag, my_call(X), X}

例外が十分に速いかどうかは、期待に依存します。私の 2.2GHz Core2 Duo Intel の速度: 1 秒間に約 200 万回の例外 (0.47us) と比較して、600 万回の (外部) 関数呼び出しの成功 (0.146us) - 例外処理には約 0.32us かかると推測できます。ネイティブ コードでは、1 秒あたり 6.8 対 4,700 万であり、処理には約 0.125us かかります。try-catch コンストラクトには、ネイティブ コードとバイト コードの両方で関数呼び出しが成功するまでに約 5 ~ 10% の追加コストがかかる可能性があります。

于 2009-03-21T10:10:40.470 に答える
4
User = get_user(),

Check_email=fun(User) -> not is_valid_email(User#user.email) end,
Check_username=fun(User) -> is_invalid_username(User#user.name) end,

case lists:any(fun(Checking_function) -> Checking_function(User) end, 
[Check_email, Check_username, ... ]) of
 true -> % we have problem in some field
   do_panic();
 false -> % every check was fine
   do_action()
 end

つまり、もう 5 レベルの深さではありません。実際のプログラムでは、すべてのチェック関数からのエラー メッセージを蓄積するために、lists:foldl を使用する必要があると思います。今のところ、「すべて問題ありません」または「何らかの問題がある」と単純に言っているからです。

このように、チェック条件を追加または削除することは大したことではないことに注意してください

そして、「return ステートメントに相当するものはありますか...」については、try catch throw ステートメントを見てください。この場合、throw は return のように機能します。

于 2009-03-20T14:03:26.533 に答える
-3

多分あなたはの使用が必要になるでしょう

receive
    message1 -> code1;
    message2 -> code2;
    ...
end.

しかし、もちろん、spawn() メソッドがあります。

于 2013-05-05T07:47:59.110 に答える