因此,函数式语言中的模式匹配非常棒。我想知道为什么大多数命令式语言都没有实现这个功能?根据我的理解,Scala是唯一的#34;主流"具有模式匹配的命令式语言。外壳/开关结构的功能不那么强大。
特别是,我感兴趣的是缺乏模式匹配是由于技术原因还是历史原因?
答案 0 :(得分:5)
这主要是历史性的。模式匹配 - 更重要的是,代数数据类型 - 是在1980年左右为功能语言Hope发明的。从那里它迅速成为ML,后来被其他功能语言如Miranda和Haskell采用。主流命令式世界通常需要花费几十年的时间才能获得新的编程语言理念。
特别阻碍采用的一个原因是主流长期以来一直由面向对象的意识形态主导。在那个世界中,任何不被物体和子类型表达的东西都被认为是道德上的“错误”。有人可能会争辩说代数数据类型与此类似。
也许还有一些技术原因使其在函数式语言中更加自然:
常规范围规则和变量的细粒度绑定结构是函数式语言的常态,但在主流命令式语言中并不常见。
特别是因为模式绑定了不可变变量。
类型检查模式匹配依赖于功能类型系统的更加良好的结构和刚性,以及它们与计算逻辑的紧密联系。主流类型系统通常远离它。
代数数据类型需要堆分配(除非你想浪费大量空间并禁止递归),并且在没有垃圾收集的情况下会非常不方便。但是,主流语言中存在的GC通常针对重量级对象而不是轻量级功能数据进行优化。
答案 1 :(得分:3)
直到最近(更准确地说:直到Scala),人们认为模式匹配与表示无知(即 定义OO的特征)不相容。由于OO是主流语言的主要范例,因此在主流语言中看似不可调和的特征似乎没有意义。
在Scala中,模式匹配与OO协调,只需将匹配操作作为对象的方法调用即可。 (事后相当简单,不是吗?)特别是,匹配是通过调用提取器对象上的方法来执行的,这些方法就像任何其他对象一样,只能访问被检查对象的公共API,因此不会破坏封装。
受Scala启发的模式匹配库,其中模式本身就是一流的对象(受F#的活动模式启发)被添加到Newspeak中,这是一种采用OO的非常动态语言非常认真。 (Newspeak甚至没有变量,只有方法。)
请注意,正则表达式是有限形式的模式匹配的示例。多态方法调度也可以看作是有限形式的模式匹配的示例(没有提取特征)。事实上,方法调度功能足以实现实现完整模式匹配,如Scala所证明,尤其是Newspeak(在后者中,模式匹配甚至实现为库,完全独立于语言)。 p>
答案 2 :(得分:0)
这是我的2美分。采用简单的Option
模式匹配:
val o = Some(1)
o match {
case Some(i) => i + 1
case None => 0
}
Scala有很多事情要发生。编译器会检查您是否有详尽的匹配,为i
语句的范围创建一个新变量case
,当然首先从Option
中提取值。
在Java等语言中提取值是可行的。实现某些商定接口的unapply
方法,您就完成了。现在您可以将值返回给调用者。
将这个提取的值提供给调用者,这实际上需要一个闭包,在没有闭包支持的常规OO语言中不太方便。在Java7中它可能变得相当丑陋,你可能会使用Observer模式。
如果您在混合中添加Scala的其他模式匹配功能,例如匹配特定类型,即case i: Int =>
;在需要时使用默认子句_
(编译器必须以某种方式检查穷举是否使用_
);其他检查,例如case i if i > 0 =>
;等等,从客户端快速变得非常丑陋(想想Java)。
如果你放弃所有那些花哨的模式匹配功能,你的模式匹配几乎就是Java switch
语句的水平。
看起来,即使可能,使用没有lambdas支持和强类型系统的匿名类也是不值得的。
答案 3 :(得分:0)
我想说这更多是出于历史而非技术原因。模式匹配适用于代数数据类型,这些数据类型在历史上也与函数式语言相关联。
Scala可能是使用模式匹配的命令式语言的一个不好的例子,因为它倾向于支持函数式,但它并没有强制执行它。
具有模式匹配的现代,主要是命令式语言的示例是Rust。 势在必行并在金属上运行,但仍然具有代数数据类型,模式匹配和功能语言更常见的其他功能。但它的'编译器实现比C编译器的实现复杂得多