You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Elixir中用with的else分支处理正常路径是否符合惯用写法?

问题

我们的代码库中有现成的类型转换函数,用于将值转为特定数据类型。我现在需要把一个未知类型的输入值,转换为数字、NaiveDateTime 或字符串三者之一。现有转换函数的返回格式是{:ok, new_value}或{:error, old_value}元组。目前我用了这样的with逻辑:

with {:error, value} <- coerce_to_number(value),
     {:error, value} <- coerce_to_naive_datetime(value),
     {:error, value} <- coerce_to_string(value) do
  :error
else
  {:ok, value} -> {:ok, value}
end

我自己习惯这种写法,也觉得with能清晰表达转换步骤,但同事不认可用else分支处理正常流程的写法。有没有更符合Elixir惯用风格的实现方式?

解决方案

方案1:用Enum.find_value遍历转换函数

把所有转换函数放进列表,依次尝试调用,直到找到第一个返回{:ok, value}的结果,这种写法贴合函数式遍历的风格,逻辑直观易懂:

def coerce_value(value) do
  [&coerce_to_number/1, &coerce_to_naive_datetime/1, &coerce_to_string/1]
  |> Enum.find_value(:error, fn coercer ->
    case coercer.(value) do
      {:ok, val} -> {:ok, val}
      {:error, _} -> nil
    end
  end)
end

Enum.find_value会逐个执行列表里的转换函数,只要某个函数返回非nil的值就直接返回该结果;如果所有函数都返回错误,就返回默认值:error。

方案2:自定义函数+模式匹配

通过多子句函数的模式匹配来依次尝试转换,这种写法完全贴合Elixir的核心特性,结构清晰,可读性强:

def coerce_value(value) do
  case coerce_to_number(value) do
    {:ok, val} -> {:ok, val}
    {:error, val} -> try_coerce_naive_datetime(val)
  end
end

defp try_coerce_naive_datetime(value) do
  case coerce_to_naive_datetime(value) do
    {:ok, val} -> {:ok, val}
    {:error, val} -> try_coerce_string(val)
  end
end

defp try_coerce_string(value) do
  case coerce_to_string(value) do
    {:ok, val} -> {:ok, val}
    {:error, _} -> :error
  end
end

把每个转换步骤拆成私有函数,层层递进,完全避免了用with的else分支处理正常流程的问题。

方案3:嵌套with(不推荐)

如果坚持想用with,可以调整为嵌套结构,让正常流程落在do块里,但这种写法嵌套较深,可读性不如前两种:

def coerce_value(value) do
  with {:ok, val} <- coerce_to_number(value) do
    {:ok, val}
  else
    {:error, val} ->
      with {:ok, val} <- coerce_to_naive_datetime(val) do
        {:ok, val}
      else
        {:error, val} ->
          case coerce_to_string(val) do
            {:ok, val} -> {:ok, val}
            {:error, _} -> :error
          end
      end
  end
end

内容的提问来源于stack exchange,提问作者Ian Mac

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 03:50:03