elixir - Elixir 中的返回语句

标签 elixir phoenix-framework

我需要一个具有某种分步逻辑的函数,我想知道如何制作一个。我们以一个站点的登录过程为例,所以我需要如下逻辑:

1) Email is present? Yes -> Go on; No -> Return an error

2) Email has at least 5 characters? Yes -> Go on; No -> Return an error

3) Password is present? Yes -> Go on; No - Return an error

And so on ...



为了实现这一点,我通常会使用 return声明,以便如果电子邮件不存在,我将退出执行该函数并使其返回错误。但是我在 Elixir 中找不到类似的东西,所以我需要一个建议。我现在能看到的唯一方法是使用嵌套条件,但也许有更好的方法?

最佳答案

这是一个有趣的问题,因为您需要执行多次检查、提前退出,并在此过程中转换某些状态(连接)。我通常按​​如下方式处理这个问题:

  • 我将每个检查实现为一个函数,它采用 state作为输入并返回 {:ok, new_state}{:error, reason} .
  • 然后,我构建了一个通用函数,它将调用检查函数列表,并返回第一个遇到的 {:error, reason}{:ok, last_returned_state}如果所有检查都成功。

  • 让我们先看看泛型函数:
    defp perform_checks(state, []), do: {:ok, state}
    defp perform_checks(state, [check_fun | remaining_checks]) do
      case check_fun.(state) do
        {:ok, new_state} -> perform_checks(new_state, remaining_checks)
        {:error, _} = error -> error
      end
    end
    

    现在,我们可以按如下方式使用它:
    perform_checks(conn, [
      # validate mail presence
      fn(conn) -> if (...), do: {:error, "Invalid mail"}, else: {:ok, new_conn} end,
    
      # validate mail format
      fn(conn) -> if (...), do: {:error, "Invalid mail"}, else: {:ok, new_conn} end,
    
      ...
    ])
    |> case do
      {:ok, state} -> do_something_with_state(...)
      {:error, reason} -> do_something_with_error(...)
    end
    

    或者将所有检查移至命名的私有(private)函数,然后执行:
    perform_checks(conn, [
      &check_mail_presence/1,
      &check_mail_format/1,
      ...
    ])
    

    您也可以查看 elixir-pipes这可能会帮助您用管道表达这一点。

    最后,在 Phoenix/Plug 的上下文中,您可以将您的检查声明为 a series of plugs and halt on first error .

    关于elixir - Elixir 中的返回语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32239919/

    相关文章:

    elixir - Elixir 中是否有 python 的 timeit 的等效模块?

    data-structures - Phoenix 1.3 (Elixir) 错误 : Myapp. Users.User.__struct__/0 未定义,无法扩展 struct Myapp.Users.User

    elixir - 为什么我得到#Ecto.Association.NotLoaded?

    Elixir/Phoenix/Timex : protocol Timex. 协议(protocol)未实现:错误

    在 Phoenix 中测试返回 nil 的虚拟字段

    elixir - 混合测试 - 测试模式与任何文件都不匹配

    stream - 从一个流中减去另一个流

    elixir - 如何在 Phoenix 中渲染透明的 gif 像素?

    erlang - Ecto 的片段允许 SQL 注入(inject)

    postgresql - 使用 Ecto 交换具有唯一约束的值的正确方法?