【问题标题】:Elixir complex pattern matching orderElixir 复杂模式匹配顺序
【发布时间】:2019-07-29 04:59:39
【问题描述】:

我正在阅读精彩的 Joy of Elixir,我正试图围绕模式匹配示例中的操作顺序展开思考。

我有清单

crew = [  
    %{name: "mal", age: 40},
    %{name: "zoey", age: 36},
]

现在我可以使用模式匹配来获取列表的第一个元素,并将名称分配给不同的变量,例如

[first = %{name: first_name} | others] = crew

我了解crew 中的第一个元素已分配给first,而first 的name 已分配给first_name:

iex> first
%{age: 40, name: "mal"}
iex> first_name
"mal"

根据示例,我还可以将名称从右到左分配给另一个变量:

%{name: first_name2} = first

但是当我从左到右尝试时同样失败:

iex> first = %{name: first_name3}
** (CompileError) iex:33: undefined function first_name3/0
    (stdlib) lists.erl:1354: :lists.mapfoldl/3
    (stdlib) lists.erl:1355: :lists.mapfoldl/3

我的问题是:为什么从左到右分配在列表匹配中可以,但在列表匹配之外失败?

【问题讨论】:

  • 变量必须已经分配在右侧。
  • @denis.peplin 那么为什么[first = %{name: first_name} | others] = crew 中不是这种情况? first_name 在 first 的右侧
  • crew 在此提供数据

标签: pattern-matching elixir


【解决方案1】:

=(匹配运算符)的右侧首先被评估。在表达式中

 first = %{name: first_name3}

它试图获取first_name3 的值,但范围内没有first_name3。

对于表达式

[first = %{name: first_name} | others] = crew

你可以把它想象成

[first = %{name: first_name} = %{age: 40, name: "mal"} | others] = crew

或

others = tl(crew)
head = hd(crew)
first = %{name: first_name} = head

这是另一个例子:

x = "foo" 将变量x 绑定到字符串"foo"(因为x 最初是未绑定的)。现在x 已经被绑定了 到"foo","foo" = x 也是一个有效的表达式,因为"foo" 匹配x。

【讨论】:

  • 很好的解释!谢谢!
【解决方案2】:

这是因为 elixir 评估序列的方式。当您启动 iex 时,您的环境将是空的。当您输入 first = %{name: first_name3} 时,它将从评估右侧开始。在实际地图中,您试图将键“名称”与变量 first_name3 相关联。如果您的环境中不存在 first_name3,则表达式将无法计算,您将收到未定义函数错误。

这应该可行:

first_name3 = "John"
first = %{name: first_name3}

【讨论】:

  • 所以我错误地认为[first = %{name: first_name} | others] = crew 中的first = %{name: first_name} 是从左到右的?
猜你喜欢
  • 2019-10-07
  • 1970-01-01
  • 1970-01-01
  • 2018-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-06
  • 2015-08-15
相关资源
最近更新 更多