tld*_*ldr 12 dictionary tuples elixir pattern-matching
在Elixir中,如果我尝试模式匹配以下两个元组:
{a} = {1, 2}
Run Code Online (Sandbox Code Playgroud)
我得到一个匹配错误.但如果我对两张地图做同样的事情:
%{x: a} = %{x: 1, y: 2}
Run Code Online (Sandbox Code Playgroud)
它工作正常,并a
绑定到1.我可以看到为什么匹配这两个元组给出了一个错误,但为什么匹配地图不会出错?
bit*_*ker 26
在第一个示例中,您尝试将单个元素元组与两元素元组进行匹配.在第二个示例中,您在左侧和右侧地图中匹配:x键.
编辑:我应该澄清有关Elixir中数据结构和模式匹配的规则.
在元组上匹配时,需要提供与整个元组结构匹配的模式.你可以使用_
,这是"全能"模式,但你仍然需要为元组的所有元素提供它.在列表上匹配时,必须在使用[a, b, c] = [1, 2, 3]
语法时匹配所有元素,或者在头部和尾部使用[h|t] = [1, 2, 3]
语法匹配.匹配地图时,您可以匹配地图中的一个或多个键,从而为您提供%{a: b} = %{a: :foo, b: :bar}
语法.
数据结构之间的语义有点不同,但是相当常见.存在元组规则是因为两个元组不能相同,除非它们具有相同数量的元素,列表具有相同的限制,但由于列表的语义,访问列表的head元素是使用时最常见的操作他们,因此[h|t]
语法.然而,地图可以根据特定的键进行匹配,因此元素的数量是无关紧要的,只要匹配的两侧包含相同的键,并且值的可选模式,那么它就是成功的匹配.
maps
,Elixir中的主要键值存储,具有一个有趣的功能,使它们在模式匹配方面与其他数据结构区别开来.
A map
实际上只能在值的子集上进行模式匹配.在图案中的密钥(或多个)具有在比赛中存在,但在两个结构不具有镜像彼此以相同的方式一个list
或一个tuple
具有到.例如:
iex(1)> [a, b] = [1, 2, 3]
** (MatchError) no match of right hand side value: [1, 2, 3]
iex(1)> {a, b} = {1, 2, 3}
** (MatchError) no match of right hand side value: {1, 2, 3}
iex(1)> %{:a => one} = %{:a => 1, :b => 2, :c =>3}
%{a: 1, b: 2, c: 3}
iex(2)> one
1
iex(3)> %{:a => one, :c => three} = %{:a => 1, :b => 2, :c =>3}
%{a: 1, b: 2, c: 3}
iex(4)> three
3
iex(5)> one
1
iex(6)> %{} = %{:a => 1, :b => 2, :c =>3}
%{a: 1, b: 2, c: 3}
iex(7)> %{:d => four} = %{:a => 1, :b => 2, :c =>3}
** (MatchError) no match of right hand side value: %{a: 1, b: 2, c: 3}
iex(8)> %{:a => one, :d => four} = %{:a => 1, :b => 2, :c =>3}
** (MatchError) no match of right hand side value: %{a: 1, b: 2, c: 3}
Run Code Online (Sandbox Code Playgroud)
如果模式的数据结构与匹配的数据结构(即大小)不同,我们可以看到既不匹配list
也不tuple
匹配.而地图不是这种情况.因为密钥在模式和匹配中都存在,所以无论模式和匹配的大小不同,匹配都是成功的.空的map
也会匹配.
但是,如果模式中的键不在匹配中,则匹配将不会成功.即使存在匹配的键也是如此.因此,模式中使用的任何键都必须出现在匹配中.
您将在Phoenix Framework中广泛地看到这种匹配,以便仅从请求中获取必要的参数.
来源: - 关于Elixir的注释:模式匹配地图