解释模式匹配vs开关
我一直在试图解释开关语句和模式匹配(F#)之间的区别,但我没有真正能够解释它..大多数时候,他们只是看着我说“那么为什么你不要只是使用..如果..“。
你将如何解释给他们?
编辑! 感谢大家的伟大的答案,我真的希望我可以标记多个正确的答案。
以前是“那些人”之一,我不知道有一个简洁的方式来总结为什么模式匹配是这样美味的善良。 这是体验。
当我刚刚浏览模式匹配,并认为这是一个荣耀的开关语句,我认为我没有经验与代数数据types(元组和歧视联盟)编程,并不完全看到模式匹配是对照构build体和结合构build体。 现在我已经用F#编程了,我终于“明白了”了。 模式匹配的好处是由于函数式编程语言中的特性的融合,所以对于局外人来说,欣赏是不重要的。
我试图总结一下为什么模式匹配在第二部分关于语言和APIdevise的短篇博客系列中有用; 检查第一部分和第二部分 。
模式给你一个小语言来描述你想要匹配的值的结构。 结构可以是任意深的,您可以将variables绑定到结构化值的一部分。
这可以让你写得非常简洁。 你可以用一个小例子来说明这一点,例如简单types的mathexpression式的微分函数:
type expr = | Int of int | Var of string | Add of expr * expr | Mul of expr * expr;; let rec d(f, x) = match f with | Var y when x=y -> Int 1 | Int _ | Var _ -> Int 0 | Add(f, g) -> Add(d(f, x), d(g, x)) | Mul(f, g) -> Add(Mul(f, d(g, x)), Mul(g, d(f, x)));;
此外,由于模式匹配是静态types的静态构造,因此编译器可以(i)validation您是否覆盖了所有情况(ii)检测到永远不会匹配任何值的冗余分支(iii)提供非常高效的实现)。
摘自本文的文章 :
与开关语句和方法调度相比,模式匹配有几个优点:
- 模式匹配可以作用于整数,浮点数,string和其他types以及对象。
- 模式匹配可以同时处理多个不同的值:并行模式匹配。 方法调度和切换仅限于单个值,例如“this”。
- 模式可以嵌套,允许调度任意深度的树。 方法调度和切换仅限于非嵌套的情况。
- Or-patterns允许共享子模式。 方法调度只允许在方法来自共享基类的类时进行共享。 否则,您必须手动将通用性分解为单独的function(给它一个名称),然后手动将来自所有适当位置的呼叫插入到不必要的function中。
- 模式匹配提供了捕获错误的冗余检查。
- F#编译器为您优化了嵌套和/或并行模式匹配。 面向对象的代码必须手工编写,并在开发过程中不断手工重新优化,这是过于繁琐和容易出错的,所以生产质量的OO代码往往比较慢。
- 活动模式允许您注入自定义调度语义。
closures我的头顶上:
- 编译器可以告诉你是否没有在你的匹配中覆盖所有的可能性
- 你可以使用一个匹配作为一个任务
- 如果你有一个歧视的工会,每场比赛可以有不同的“types”
元组有“,”和变体有Ctor args ..这些是构造函数,他们创造的东西。
模式是破坏者,他们撕裂他们。
他们是双重概念。
更有力的说:元组或变体的概念不能仅仅由其构造函数来描述:析构函数是必需的,或者你所做的值是无用的。 正是这些定义价值的双重描述。
一般来说,我们将构造函数看作数据,将析构函数看作控制stream。 变体析构函数是可选分支(许多中的一个),元组析构函数是并行线程(全部是很多)。
在类似的操作中,并行性是显而易见的
(f * g) . (h * k) = (f . h * g . k)
如果你想到控制stream经一个函数,元组提供了一种将计算分解成并行的控制线程的方法。
看着这种方式,expression式是组成元组和变体的复杂数据结构的方式(想象一下AST)。
和模式匹配是组成析构函数的方法(再次,考虑AST)。
开关是两个前轮。
模式匹配是整个车。
在OCaml中的模式匹配,除了如上所述的以几种方式提到的更具performance力之外,还提供了一些非常重要的静态保证。 编译器会为您certificate您的模式匹配语句所体现的案例分析是:
- 详尽无遗(没有错过的情况下)
- 非冗余的(没有任何情况是不可能的,因为它们被先前的情况所占领)
- 声音(在给定数据types的情况下,没有模式是不可能的)
这真是一件大事。 当你第一次编写程序的时候,这很有帮助,当你的程序正在发展的时候,它是非常有用的。 正确使用匹配语句可以更容易地更改代码中的types,因为types系统指向破坏的匹配语句,这是指示您需要修复代码的位置。
如果else(或switch)语句是关于根据当前值的属性select不同的方式来处理值(input)。
模式匹配是关于如何处理给定其结构的值(也注意单个模式匹配是有意义的)。
因此,模式匹配更多的是解构数值而不是做出select,这使得它们成为在归纳结构(recursion联合types)上定义(recursion)函数的一个非常方便的机制,这就解释了为什么它们在Ocaml等语言中被大量使用。
PS:你可能知道模式匹配和If-Else“模式”是从他们在math中临时使用的;
“如果x有属性A,那么y其他的z”(If-Else)
“p1..pn中的某个术语,其中….是x的素数分解”((单例)模式匹配)
也许你可以用string和正则expression式来比喻一下吗? 你描述你正在寻找的东西,让编译器找出自己的方式。 它使你的代码更简单,更清晰。
顺便说一下:我发现模式匹配最有用的地方是鼓励良好的习惯。 我首先处理angular落案件,很容易检查我已经涵盖了每一个案例。