2016-06-21 41 views
3

我正在学习Elixir,并且看不到优于ol开关盒的模式匹配的优势。我错过了什么?模式匹配:优于开关情况?

+0

不同的语言,相同的问题:http://stackoverflow.com/questions/21355060/what-is-the-advantage-of-using-scala-pattern-matching-instead-of-java-switch-cas – JJJ

回答

6

总之,Elixir的模式匹配case将使您的专注于您的数据形状。不要只考虑语言中的任何表达方式,并寻找真实的条件,而是向读者展示数据中需要考虑的重要因素。这是更多的意图揭示。

Elixir有casecond。前者需要一个值并在其上运行不同的模式匹配。后者不会带来价值,而是会对某些表达式进行评估,直到找到真正的表达式。 A 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区块内可用,不会“泄漏”。

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

0

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的优点是什么?

在这种情况下,它是一种风格/偏好。但是,它确实减少了您的功能的大小。我更喜欢多功能原因的方法,特别是如果每​​个代码块很大。