Elixir中如何返回第一个真值?符合函数式风格的惯用方案
符合Elixir惯用风格的实现方案
核心用标准库自带的Enum.find_value/3即可实现需求,这个函数原生支持按顺序执行检查、返回第一个非假值、无匹配返回默认值的逻辑,不需要重复调用测试函数,也没有冗余分支。
实现代码
def some_function(input) do # 按执行顺序把测试函数放进列表,新增测试只需扩展列表即可 tests = [&test1/1, &test2/1] Enum.find_value(tests, {:error}, fn test -> test.(input) end) end def test1({:some, :case}), do: false def test1({:some, :other, :case}), do: {:ok} def test2({:some, :case}), do: false def test2({:some, :other, :case}), do: {:ok}
逻辑说明
- 测试函数按优先级顺序存入列表,后续新增校验规则只需在列表中追加函数引用,无需修改核心判断逻辑
Enum.find_value/3会依次调用列表中的测试函数,传入待校验的输入值- 只要某个测试函数返回的值不是
false或nil,就会直接返回该值,终止后续测试执行 - 所有测试都返回假值时,自动返回默认值
{:error}
可选优化
如果测试函数数量较多,可以把测试列表提取为模块属性,避免每次调用都重复生成列表:
# 模块属性只会在编译时生成一次 @tests [&test1/1, &test2/1] def some_function(input) do Enum.find_value(@tests, {:error}, fn test -> test.(input) end) end
原代码问题说明
你之前用or实现的代码报错,是因为Elixir的or是严格布尔运算符,要求左右两边都必须是布尔值,{:ok}不是布尔值所以触发类型错误。Enum.find_value没有这个限制,只要返回值不是nil/false就会被当作有效值返回,刚好适配你的场景。
内容的提问来源于stack exchange,提问作者sconstable
相关产品推荐
相关产品推荐

