了解 Elixir 函数参数中的模式匹配

2024-01-17

在《Elixir in Action》一书中,其中一个示例的一个函数颠覆了我对模式匹配的理解:

def add_entry(
    %TodoList{entries: entries, auto_id: auto_id} = todo_list,
    entry
  ) do
    entry = Map.put(entry, :id, auto_id)
    new_entries = HashDict.put(entries, auto_id, entry)

    %TodoList{todo_list |
      entries: new_entries,
      auto_id: auto_id + 1
    }
 end

第一个参数,%TodoList{entries: entries, auto_id: auto_id} = todo_list,这本书解释说“......此外,你将整个实例保存在一个todo_list多变的”

这让我很困惑,因为我认为变量绑定在“=”模式匹配运算符的左侧。有人可以帮助解释第一个参数发生了什么以及如何在函数体内使用传入值吗?


带变量:

iex(2)> x = %{a: 1, b: 2}   
%{a: 1, b: 2}

iex(3)>  %{a: 1, b: 2} = y
** (CompileError) iex:3: undefined function y/0

对于函数参数变量:

defmodule A do

  def go1(z = %{a: a}) do
    IO.inspect z
    IO.puts a
  end

  def go2(%{a: a} = z) do
    IO.inspect z
    IO.puts a
  end

end

In iex:

iex(4)> c "a.ex"  
warning: redefining module A (current version defined in memory)
  a.ex:1
[A] 

iex(5)> map = %{a: 1, b: 2} 
%{a: 1, b: 2}

iex(6)> A.go1(map)
%{a: 1, b: 2}
1
:ok

iex(7)> A.go2(map)
%{a: 1, b: 2}
1
:ok

函数参数与函数参数变量进行模式匹配。并且,在 Elixir 函数中参数可以是常量,例如1 或原子、映射、元组等——不仅仅是一个变量,如 x、y 或 z。这是如何go1() works:

    A.go1(%{a: 1 b: 2})
          |-----+----|
                |
                | %{a: a} = %{a: 1 b: 2} 
                V
def go1(z = %{a: a}) do

“参数变量”是%{a: a},并且它与函数参数匹配%{a: 1 b: 2},这绑定了a to 1。然后,您可能认为您获得了模式匹配:z = %{a: 1},但是,模式匹配%{a: a} = %{a: 1 b: 2}实际上返回右侧:

iex(10)> %{a: a} = %{a: 1, b: 2}    
%{a: 1, b: 2}

因此,您会得到模式匹配:z = %{a: 1, b: 2}。这是另一个演示:

iex(13)> z = %{a: a} = %{a: 1, b: 2}
%{a: 1, b: 2}

iex(14)> a
1

iex(15)> z
%{a: 1, b: 2}

这是如何go2() works:

      A.go1(%{a: 1 b: 2})
            |-----+----|
                  |
                  | z = %{a: 1, b: 2}
                  V
def go2(%{a: a} = z)

z是参数变量,它与函数参数匹配%{a: 1 b: 2}。比赛z = %{a: 1 b: 2}返回右侧:

iex(10)> z = %{a: 1, b: 2}
%{a: 1, b: 2}

所以,接下来你会得到模式匹配:%{a: a} = %{a: 1, b: 2},这绑定了a to 1.

因此,一切都是一致的:对于每个模式匹配,包含变量的模式位于=,值位于右侧。如果你正在寻找一条规则,那就是:在函数定义的参数列表中,右边的东西=符号是“参数变量”。左边的东西是一个模式,在“参数变量”与函数参数匹配之后(或者正如您在其他语言中所说的:“在函数参数分配给参数变量之后”),它将被匹配。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

了解 Elixir 函数参数中的模式匹配 的相关文章

随机推荐