我最近购买了 Programming Scala ,并一直在阅读它。语言肯定不是我的预期!具体来说,除了Lisp宏和Haskell的类型级别副作用隔离之外,它似乎实现了我所知道的几乎所有编程语言的想法。
坦率地说,它让我有点不知所措。虽然我认为拥有这么多工具很好,但我真的只是在JVM上寻找一种强类型的函数式语言。我想我可能会以这种方式使用Scala,但我想如果我与任何库交互或通过其他人的代码,我会遇到很多这种高级(对我而言)OOP的东西 - 特征和“对象层次结构”线性化,“所有这些抽象和重要的业务,单例,包和伴随对象,隐式转换......更不用说各种语法快捷方式和糖。人们经常哀叹那些试图将一种语言的风格融入另一种语言的程序员,原因很多。但并非所有语言都像Scala一样具有多范式,所以也许它的社区有不同的看法?例如,在F#中,编程风格和使用的OOP似乎有一些余地。但仅仅是从阅读中我不确定这对Scala来说是否也是一个好的哲学。
更有经验的Scala程序员可以帮助我吗? 为了清晰起见编辑:基本上,我是否可以安全地使用Scala的FP功能而不用担心其高级OOP端?
抱歉这个漫无边际的问题!
答案 0 :(得分:16)
您所看到的一件事是,Scala首先是JVM上强类型的函数语言
Scala不是只是一种功能语言。它确实从一开始(漏斗:http://lamp.epfl.ch/funnel/),但后来扩展为使其成为面向对象的语言,其明确目标是使其与Java类强大地互操作。
抽象和覆盖以及包都是这种互操作性的例子。
其余部分可能不被视为新功能,而只是从Java中删除限制。一次带一个:
特征和对象层次结构线性化
删除Java接口只能包含抽象方法的限制。线性化是Scala如何解决钻石继承问题的原因。
<强>单身强>
Java静态方法是它的C ++语法遗产的宿醉,它反过来又添加它们以更好地支持与C互操作的程序样式需求。静态方法非常不面向对象(请参阅此问题:Why are singleton objects more object-oriented? )
随播广告
允许使用单例代替静态方法,具有其特权访问权限。
隐式转化
Java已经这样做了,但它仅限于隐式地将对象和基元转换为字符串,如表达式"" + 3
中所示。 Scala只是扩展了这个想法,并允许程序员将其用于其他转换。
答案 1 :(得分:8)
让我在凯文的回答中加上一些评论。
Traits主要用作抽象(松散地说,与Haskell类型类定义抽象的方式相同)和mixins。所以,我的代码可能会使用Map trait,但它确实使用了像HashMap这样的类型的实例。相反,如果我希望我的“服务”类型具有日志记录功能,我可能会混合使用可重用的日志记录特征。
幸运的是,除了简单的情况之外,你很少考虑线性化算法,例如,我可以混合一个截取(包装)方法调用的特征来记录调用该方法的事实。算法需要处理更复杂的线性化情况(就像我们在书中展示的例子一样),但实际上这种复杂的类型设计很差,恕我直言。
Singletons,包括特殊子集伴随对象,旨在使所有东西成为一个对象,但你也可以只将它们视为命名空间包装函数和可能的某些状态。
隐式转换非常有用,如果有点“神奇”。您可能会发现查看它们如何用于模拟Haskell类型类很有用。这是Debasish Ghosh写的一篇精彩文章:http://debasishg.blogspot.com/2010/06/scala-implicits-type-classes-here-i.html
答案 2 :(得分:7)
我认为这个问题肯定有一个重点。通过研究任何库如何处理例外来阐明它。
如果您与Java库交互,任何方法都可能抛出异常。这可以通过 checked 异常显式地,或者通过运行时异常透明地(从API角度来看)。作为一个程序员可能会尝试使用功能更强大的Either
类型来表示失败(或 scalaz 的Validation
),你应该怎么做呢? / p>
对我来说,这一点在scala中是如何发挥的(即接近问题和选择纯粹的功能方法)并不是很清楚。当然,它很可能产生许多不同风格的编码。也就是说,scala的功能方面有很多丰富而有用的东西可以选择;当然,在您的程序中将功能和命令性代码混合在一起是可能的。虽然功能 purist 当然可能不同意这是否是最佳情况。
对于它的价值,我发现在我的程序中应用功能范例已经改进了我的代码。由于我没有尝试 Haskell 或 F#,我无法告诉您净结果是好还是坏。
但它用Java擦拭了地板;并且从我的角度来看,在JVM上获得 (具有与我们所有Java库共存的实际优势)是一个杀手级的应用程序。
在边缘,当你开始更多地使用scala的功能方面时,你会遇到许多问题。这些是最明显的:
A => B => C
和(A, B) => C
的等效性M[A]
与Either[Int, A]
的等价性)这两个问题都使得功能代码变得非常清晰,丑陋和模糊。
答案 3 :(得分:3)
虽然我已经开始使用scala编程,但我绝对不是scala社区中经验丰富的成员。但是我已经使用了另一种语言 - python,它在较小程度上也有类似的情况。它支持过程,面向对象和功能样式。我发现虽然有些人倾向于坚持一个极端,但许多人结合了不同风格的结构。因此,惯用的python将包括大量使用列表推导,第一类,高阶和部分函数,即使这些函数处理的数据是对象。然而,值得注意的是,多年来,趋势已逐渐转向功能性。
我认为考虑到scala支持的样式的包容性,很可能没有一种正确的方法来解决问题。但是,我不会感到惊讶的是,更多的程序员慢慢倾向于明智地使用两者,即使他们仍然容忍程序员希望坚持一个极端。