Mer*_*kos 3 elixir pattern-matching
我看到了这个片段,但我不明白这是如何通过模式匹配来完成的。如果有人可以向我(或其他可能不理解这一点的人)解释一下,那就太好了
def even_length?([]) do
true
end
def even_length?([_head | tail]) do
!even_length?(tail)
end
Run Code Online (Sandbox Code Playgroud)
当给出诸如[1, 2]或 之类的输入时,我只是迷失了方向[3, 4, 5]
提前致谢。
代码来源:https://gist.github.com/mauricoabreu/8fdb64bef6a938dd1e34ac15e9268d4d
这是一段非常聪明的代码,但如果您逐步遵循它的执行过程,可能会更容易理解。
在我们看几个例子之前,重要的是你要了解 Elixir 将列表实现为链接列表,并且每个列表都有 ahead和 a tail,其中尾部本身是一个单独的列表术语。每个列表(空列表除外)都可以写成[ head | tail ]:
[1] == [ 1 | [] ]
# => true
[3, 2, 1] == [ 3 | [2, 1] ]
# => true
[3, 2, 1] == [ 3 | [ 2 | [ 1 | [] ] ] ]
# => true
Run Code Online (Sandbox Code Playgroud)
[]调用even_length?([])将匹配第一个签名并直接返回true,因为这是我们的递归函数的基本情况。
[x]当在具有一个元素的列表上调用函数时,VM 将跳过第一个函数定义(因为它不为空),并继续执行第二个函数定义,该函数又在尾部递归调用该函数并反转布尔值。如果我们扩展调用堆栈,它将如下所示:
even_length?([1]) # `1` is head, `[]` is tail
# => !even_length?([])
# => !(true) # We know value is `true` from base-case
# => false
Run Code Online (Sandbox Code Playgroud)
[x, y]同样的事情,但我们将再次反转结果(因为该函数将被额外调用一次):
even_length?([2, 1]) # `2` is head, `[1]` is tail
# => !even_length?([1]) # `1` is head, `[]` is tail
# => !(!even_length?([]))
# => !(!(true)) # We know value is `true` from base-case
# => !(false)
# => true
Run Code Online (Sandbox Code Playgroud)
[x, y, z]even_length?([3, 2, 1]) # `3` is head, `[2, 1]` is tail
# => !even_length?([2, 1]) # `2` is head, `[1]` is tail
# => !(!even_length?([1])) # `1` is head, `[]` is tail
# => !(!(!even_length?([])))
# => !(!(!(true))) # We know value is `true` from base-case
# => !(!(false))
# => !(true)
# => false
Run Code Online (Sandbox Code Playgroud)
[ ... ]并且这种情况还会继续重复。理解此函数功能的最简单方法是,它定义了包含 0 个元素的 List 应返回true,并且对于每个额外元素,它应反转(布尔值not)先前的值。
| 归档时间: |
|
| 查看次数: |
450 次 |
| 最近记录: |