【问题标题】:Pattern matching: advantage over switch-case?模式匹配:优于 switch-case?
【发布时间】:2017-04-14 01:48:13
【问题描述】:

我正在学习 Elixir,但看不到模式匹配优于良好的开关案例的优势。我错过了什么?

【问题讨论】:

标签: pattern-matching elixir


【解决方案1】:

简而言之,Elixir 的模式匹配case 将使您专注于数据的形状。不是允许语言中的任何表达式,而是寻找真实的条件,而是向读者展示数据中需要考虑的重要形状。更显意图。

Elixir 同时拥有case 和cond。前者接受一个值并在其上运行不同的模式匹配。后者不取值,而是评估一些表达式,直到找到一个为真的表达式。 cond 的作用类似于 if … elseif … else。

list = [3,2,1]
string = "abc"

case list do
  []        -> :empty             # won't match
  [1 | t]   -> :starts_with_one   # won't match
  [3, b, c] -> "3, #{b} and #{c}" # match!
  _         -> :fallback          # _ would match anything
end

cond do
  List.last(list) == 2     -> :two_at_the_end # false
  length(string) == 3      -> :three_letters  # true
  true                     -> :fallback
end

如您所见,cond 中的表达式实际上没有任何联系。他们不必对相同的数据采取行动。您还可以使用模式匹配中不允许的表达式。这两个方面都使cond 非常灵活,但它也有点代码味道。块没有连贯性。表达式可能有副作用。我需要更仔细地查看cond 而不是case。

相比之下,case 表达式让我非常明确地推断出我的数据的形状。所有的匹配都是在相同的数据上完成的,所以它具有自然的凝聚力。它告诉读者很多关于作者对一些数据的期望。这是非常意图揭示。它快速显示了作者期望数据采取的形状,以及应该区别对待的任何特殊情况。阅读case 语句时,您也可以专注于数据。

模式匹配还可以让您捕获部分模式。我捕获匹配模式中的第二个和第三个列表元素。它们仅在 case 块内可用,不会“泄漏”出来。

模式匹配中允许的受限表达式集也意味着它通常非常快。

【讨论】:

    【解决方案2】:

    case 语句实际上是模式匹配。 case 语句中的每个匹配项都是一个匹配项,可用于提取匹配项的片段。此外,它还支持守卫。例如:

    case my_map do
      %{type: 1, data_for_1: data} -> "Data 1 is %{data}"
      %{type: 2, data_for_2: data} => "Data 2 is %{data}"
      map -> "No matching type found: %{inspect map}"
    end
    

    现在,也许您想问,使用 case 比使用多个函数头有什么优势?

    在这种情况下,这是风格/偏好的问题。但是,它确实减小了函数的大小。我更喜欢多函数原因的方法,尤其是在每个代码块很大的情况下。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-17
      • 2011-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多