【问题标题】:Unexpected empty list from Erlang list-comprehension来自 Erlang 列表理解的意外空列表
【发布时间】:2016-03-29 16:37:45
【问题描述】:

我使用列表推导将数据库行从元组列表转换为映射列表。有一天,我在我的数据库表中添加了一些新列,却忘记在任何地方更改代码。 因此我发现了一个奇怪的效果:数据库行变成了一个空列表。

erl 控制台中的代码示例:

> DbRows = [{1, 1, 1}, {2, 2, 2}].
[{1,1,1},{2,2,2}]
> [#{<<"col1">> => Col1, <<"col2">> => Col2} ||{Col1, Col2} <- DbRows].
[]

在这种情况下,为什么 Erlang 不产生异常错误:右侧值不匹配

这段代码可以吗,或者其他一些语法更适合执行这种数据转换?

【问题讨论】:

    标签: erlang list-comprehension


    【解决方案1】:

    Erlang 不会产生任何异常,因为这是正确的语法。生成器{Col1, Col2} &lt;- DbRows同时是一个过滤器。因此,任何与模式不匹配的元素都会被跳过。 在你的情况下,我会这样做:

    -define(FIELDS, [id, some1, some2]).
    DbRows = [{1, 1, 1}, {2, 2, 2}].
    Prepare = fun(X) ->
        maps:from_list(lists:zip(?FIELDS, tuple_to_list(X)))
    end.
    [ Prepare(Row) || Row <- DbRows].
    

    当您添加新字段时,您需要在宏中添加该字段。

    【讨论】:

    • 这也不会抛出 OP 期望的异常。获得部分答案可能总比没有好,但这也会使发现错误变得更加困难。
    • 如果您真的需要例外,只需将Prepare = fun(X) 替换为Prepare = fun(X = {_,_}),但我认为这不是重点。
    【解决方案2】:

    我不喜欢这个“功能”,因为根据我的经验,它往往会掩盖错误,但 nikit 的回答是关于您看到的结果的原因是正确的。

    您可以通过将模式匹配移动到列表推导的左侧来获取异常:

    [ case Row of {Col1, Col2} -> #{<<"col1">> => Col1, <<"col2">> => Col2} || Row <- DbRows ]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-06
      • 2012-06-24
      • 1970-01-01
      • 2010-09-18
      相关资源
      最近更新 更多