什么是模式匹配?
如果你是这个功能的新手,欢迎来到典型的 "模式匹配之旅";首先,你不知道它是什么,然后,你不理解它,最后,你不知道没有它你怎么能工作。
模式匹配功能包括检查给定预期结果或模式的数据。有些人倾向于将模式匹配与Regex(正则表达式)相混淆,因为这种搜索工具允许我们找到并替换可搜索的字符串模式。模式匹配远不止于此,我们可以说它是Regex的进化,因为它使我们不仅可以处理字符串模式,还可以处理数组、哈希和任何其他对象。
使用模式匹配简化了代码,因为它的语法是直观的和声明性的。正如你将看到的,我们写的是预期的结果,而不是必须分解组件和创建复杂的结构,使用循环和条件,如if ... elsif ... else 。
Ruby的语法
Ruby中的模式匹配语法与条件性案例语句非常相似,但我们没有使用case when ,而是使用case in ,如下图所示。
case <variable or expression>
in <pattern1>
...
in <pattern2>
...
else
...
end
该语法允许对一个或多个模式进行匹配,包括变量和表达式。注意,在每个模式之后,我们可以添加一个if或except语句来创建一个防护。
case <variable or expression>
in <pattern2> if <expression>
...
else
...
end
现在我们已经看到了模式匹配的基本语法,我们将能够理解它是如何工作的,以及将帮助我们充分利用这一功能的附加组件。
模式匹配在Ruby中是如何工作的?
让我们从一个简单的例子开始,熟悉一下匹配功能。
a = ["Paul", 27]
case a
in [String, Integer]
p "match"
else
p "not match"
end
#=> match
在这个例子中,我们要验证给定的表达式["Paul", 27] 是否符合在数组的第一个位置有一个字符串元素,在第二个位置有一个整数的模式。同样的逻辑也可以应用于哈希值,如下图所示。
case {name: "Paul", age: 27}
in {name: "Paul"}
p "Hi #{:name}!"
else
p "not match"
end
#=> Hi Paul!
在哈希中应用模式匹配允许我们检查哈希的子集,比如在这个例子中,只有名字在模式中被验证。虽然在匹配数组时,整个数组确实被考虑在内,但有一个简单的变通方法,即通过使用* 告诉Ruby我们不需要考虑某些元素。
a = ["no", "no", "YES", "no"]
case a
in [*, "YES", *]
p "match"
else
p "not match"
end
#=> match
当然,模式匹配也允许匹配更复杂的嵌套数组和哈希的结构,这对于避免混乱的循环和条件函数特别有用。对于这个问题,理解绑定和固定的概念是非常重要的,在表达式和模式结构中使用变量时,这些概念会发挥作用。
模式匹配:绑定变量
绑定的概念意味着,当把一个变量匹配到一个值时,验证不仅是真实的,而且变量将被重新分配到给定的值。让我们看一个使用两个变量的例子,a 和b 。
case ["book", "table", "chair" ]
in [a, b, "chair"]
p "variable a is #{a} and b is #{b}."
end
#=> variable a is book and b is table.
在这种情况下,模式匹配后,变量a和b分别被分配为 "book "和 "table "的值。
钉住变量
顾名思义,钉住变量是用来评估一个变量的值而不重新分配它。虽然绑定变量是一种默认行为,但要钉住一个变量,必须使用^ 。
case ["book", "table", "chair" ]
in [a, ^a, "chair"]
p "match"
else
p "not match"
end
#=> not match
在这个例子中,模式没有被匹配,因为当验证时,逐个元素的变量首先被匹配并被重新分配到a = "book" ,但随后不可能针对"table" 来验证钉住的变量^a ,因为"book" != "table" 。
使用案例
在清楚地了解了这个功能以及它是如何验证和匹配模式的之后,现在的问题是。什么时候实现它?还有,为什么它在构建基于MVC架构的应用程序时特别有用?
- 创建守护和验证,在阅读代码时容易理解,因此容易更新。
- 处理Json数据。这是非常了不起的,因为Json文件被结构化为哈希值,使用模式而不是条件函数可以极大地减少复杂性和代码。
- 在应用程序中确定范围和识别奇怪的行为。
- 在开发具有许多控制器和模型的大型界面时,通过在每个类中使用特殊方法,使模式匹配更加直观,从而创造最佳实践。这种特殊的方法是
deconstruct和deconstruct_keys。阅读这个关于deconstruct的教程,可以更好地理解这些方法。
总结
模式匹配功能在Ruby中是比较新的。它在Ruby 2.7中首次发布,并在3.1版本中得到改进。因此,仍然有空间来进一步改善它目前的性能并创建新的方法来支持它。
在开始的时候,它可能看起来很复杂,或者只是更容易继续使用条件语句,但是一旦你开始玩这个功能,你就会发现它是多么强大,以及在与其他开发者一起工作时,它的声明性的好处。