F# 解释模式匹配与切换
我一直在试图向一些人解释switch语句和模式匹配(F#)之间的区别,但我并不能很好地解释清楚。大多数时候,他们只是看着我说:“那么为什么不使用if..then..else呢?” 你会如何向他们解释F# 解释模式匹配与切换,f#,pattern-matching,ocaml,sml,F#,Pattern Matching,Ocaml,Sml,我一直在试图向一些人解释switch语句和模式匹配(F#)之间的区别,但我并不能很好地解释清楚。大多数时候,他们只是看着我说:“那么为什么不使用if..then..else呢?” 你会如何向他们解释 编辑!谢谢大家的好答案,我真的希望我能标记多个正确答案 也许你可以用字符串和正则表达式做个类比?您可以描述您正在寻找的内容,并让编译器自行决定如何查找。它使您的代码更加简单和清晰 顺便说一句:我发现模式匹配最有用的地方是它鼓励良好的习惯。我先处理角落案例,很容易检查我是否涵盖了每一个案例。我以前是“
编辑!谢谢大家的好答案,我真的希望我能标记多个正确答案 也许你可以用字符串和正则表达式做个类比?您可以描述您正在寻找的内容,并让编译器自行决定如何查找。它使您的代码更加简单和清晰
顺便说一句:我发现模式匹配最有用的地方是它鼓励良好的习惯。我先处理角落案例,很容易检查我是否涵盖了每一个案例。我以前是“那些人”中的一员,我不知道有什么简洁的方法来总结为什么模式匹配如此美味。这是经验性的 当我刚刚浏览了模式匹配并认为它是一个美化的switch语句时,我认为我没有使用代数数据类型(元组和有区别的并集)编程的经验,也不太明白模式匹配既是一个控制构造又是一个绑定构造。现在我已经用F#编程了,我终于“明白了”。模式匹配之所以如此酷,是因为函数式编程语言中的各种特性汇集在一起,因此,对于旁观者来说,欣赏模式匹配绝非易事
在关于语言和API设计的两部分博客系列的第二部分中,我试图总结模式匹配为什么有用的一个方面;查看并从我的头顶上删除。:
模式为您提供了一种小语言来描述要匹配的值的结构。结构可以是任意深度,并且可以将变量绑定到结构值的部分 这可以让你非常简洁地写东西。您可以用一个小例子来说明这一点,例如一种简单数学表达式的导数函数:
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)));;
此外,由于模式匹配是静态类型的静态构造,编译器可以(i)验证您是否涵盖了所有情况(ii)检测无法匹配任何值的冗余分支(iii)提供非常有效的实现(使用跳转等)。开关是两个前轮 模式匹配是指整个汽车。摘自: 与开关语句和方法调度相比,模式匹配有几个优点:
- 模式匹配可以作用于int, 浮点数、字符串和其他类型 以及对象
- 模式匹配可以作用于多个 同时使用不同的值: 并行模式匹配。方法 调度和切换仅限于单个 值,例如“this”
- 模式可以嵌套,允许 任意树上的调度 深度方法调度和切换受到限制 对于非嵌套的情况
- 或模式允许创建子模式 共享。方法分派只允许 当方法来自时共享 碰巧共享一个基的类 班级。否则必须手动执行 将共性因素分解成一个整体 单独的功能(给它一个 然后手动插入呼叫 从所有合适的地方到你的 不必要的功能
- 模式匹配提供冗余 检查哪些捕获错误
- 嵌套和/或并行模式 匹配项由 F#编译器。OO等价物必须 经常手写 在运行期间手动重新优化 发展,这是令人望而却步的 这样做既乏味又容易出错 产品质量OO代码倾向于 相比之下,速度要慢得多
- 活动模式允许您注入 自定义分派语义
- 详尽无遗(无遗漏案例)
- 非冗余(没有因为被前一个案例抢先而无法命中的案例)
- 声音(考虑到所讨论的数据类型,没有不可能的模式)
(f * g) . (h * k) = (f . h * g . k)
如果您认为控件流经一个函数,元组提供了一种将计算拆分为控件的并行线程的方法
从这个角度看,表达式是组成元组和变体的方法,以形成复杂的数据结构(比如AST)
模式匹配是组成析构函数的方法(同样,考虑AST)。