代码之家  ›  专栏  ›  技术社区  ›  J Cooper

Scala中坚持功能范式的有效性

  •  16
  • J Cooper  · 技术社区  · 14 年前

    我最近买的 编程Scala ,一直在通读。语言绝对不是我所期望的!具体来说,它似乎实现了我所知道的几乎所有编程语言思想,除了Lisp宏和Haskell的类型级副作用分离之外。

    坦白说,这让我有些不知所措。尽管我认为有这么多工具可以使用是件好事,但我实际上只是在JVM上寻找一种强类型函数语言。我想我可以用这种方式使用Scala,但我想如果我与任何库交互或浏览任何其他人的代码,我会遇到很多高级(对我来说)OOP的东西——traits和“对象层次线性化”,所有这些抽象和重写的业务,singleton,package,和同伴对象,隐式转换。。。更不用说各种各样的语法捷径和甜点了。

    人们常常哀叹那些试图将一种语言的风格塞进另一种语言的程序员,理由很多。但并不是所有的语言都像Scala那样具有多范式,所以它的社区可能有不同的观点?例如,在F#中,编程风格和使用OOP的程度似乎有一定的回旋余地。但仅仅从阅读的角度来看,我不确定这对Scala来说是否也是一个好的哲学。

    有经验的Scala程序员能帮我吗? 为了清晰起见,请编辑: 基本上,我可以安全地使用Scala的FP特性而不必担心它的高级OOP端吗?

    对不起,这个问题太离谱了!

    4 回复  |  直到 14 年前
        1
  •  7
  •   oxbow_lakes    14 年前

    我认为这个问题肯定有一个坚实的论点。它是通过研究任何一个库如何处理 例外情况 .

    如果与Java库交互,任何方法都可能抛出异常。这可以是显式的,通过 选中的 异常-或透明地(从API的角度),通过 运行时 例外。作为一个程序员,你应该怎么做呢,他可能会试图使用 Either 指示故障的类型(或 色拉 Validation )?

    我一点也不清楚这在scala中是如何实现的(即解决问题并选择纯功能的方法)。当然有可能 许多不同的风格 编码。也就是说,在scala的功能方面有很多东西是丰富和有用的,您可以从中选择;而且在您的程序中,功能性代码和命令性代码的这种混合肯定是可以一起工作的。尽管是功能性的 纯粹主义者 当然,梅不同意这是否是一个最佳的情况。

    值得一提的是,我发现在我的程序中应用函数范式改进了我的代码。因为我也没试过 哈斯克尔 F型# 我不能告诉你结果是好是坏。

    但它用爪哇擦地板 在JVM上 (与我们所有的Java库共存的实际优势)是一个杀手级应用程序,从我的角度来看。


    在边缘,当您开始更多地使用scala的函数端时,会遇到许多问题。最明显的是:

    • 隐性功能的缺失 咖喱 (即 A => B => C (A, B) => C )
    • 隐性功能的缺失 元组 (即n元函数与以n元组为参数的1元函数之间的等价性)
    • 缺乏对部分应用类型构造函数的推理(即 M[A] 例如, Either[Int, A] )

    这两个问题都使得本应清晰明了的功能代码变得丑陋和晦涩。

        2
  •  16
  •   Community chadoh    7 年前

    你看到的一件事是Scala首先是一种强类型函数语言 在JVM上

    斯卡拉不是 只是 功能性语言。一开始确实是这样(漏斗: http://lamp.epfl.ch/funnel/ ),但随后对其进行了扩展,使其成为一种面向对象的语言,其明确目标是使其与Java类具有很强的互操作性。

    抽象、重写和包都是这种互操作性的实例。


    剩下的部分可能不被视为新特性,而只是从Java中删除限制。一次吃一个:

    特征与对象层次线性化

    移除Java接口只能包含抽象方法的限制。线性化是Scala解决钻石继承问题的方法,否则会导致钻石继承问题。

    单重态

    Java静态方法是C++语法遗产的遗留问题,它又添加了它们来更好地支持用C语言来处理程序间的风格。静态方法非常不面向对象(见这个问题: Why are singleton objects more object-oriented? )

    伴生物体

    允许使用具有特权访问权限的singleton来代替静态方法。

    隐式转换

    Java已经这样做了,但它仅限于隐式地将对象和原语转换为字符串,如在表达式中 "" + 3 . Scala只是扩展了这一思想,允许程序员将其用于其他转换。

        3
  •  8
  •   Dean Wampler    14 年前

    让我对凯文的回答补充几点意见。

    特征主要用作抽象(松散地说,与Haskell类型类定义抽象的方式相同)和混合。所以,我的代码可能使用了Map特性,但它实际上使用了HashMap类型的实例。相反,如果我希望我的“服务”类型具有日志记录功能,我可以混合使用可重用的日志记录特性。

    幸运的是,除了简单的例子之外,您很少需要考虑线性化算法,例如,我可以混合使用一个特性来截取(包装)方法调用以记录调用该方法的事实。该算法需要处理更复杂的线性化情况(如我们在书中展示的例子),但真正如此复杂的类型是一个糟糕的设计,IMHO。

    单例,包括特殊的子集伙伴对象,被设计为使所有对象成为一个对象,但是您也可以将它们看作是名称空间包装函数和一些状态。

    隐式转换非常有用,如果有点“神奇”。您可能会发现了解如何使用它们来模拟Haskell类型的类是很有用的。这是德巴西斯·戈什的一篇很好的文章: http://debasishg.blogspot.com/2010/06/scala-implicits-type-classes-here-i.html

        4
  •  3
  •   Dhananjay Nene    14 年前

    虽然我已经开始用scala编程,但我绝对不是scala社区中经验更丰富的成员。但我已经用了很长时间的另一种语言——python,它在较小程度上也有类似的情况。它支持程序、面向对象和功能样式。我发现,虽然有些人倾向于坚持一个极端,但许多人将不同风格的结构结合在一起。因此,惯用的python将包含大量使用列表理解、第一类、高阶和部分函数,即使这些函数处理的数据是对象。然而,值得注意的是,多年来,这一趋势一直在向功能性转变。

    我认为考虑到scala支持的风格的包容性,很可能没有一种正确的方法来解决问题。但是,当我看到一个更大比例的程序员慢慢地倾向于一种明智地使用两者的风格时,我不会感到惊讶,即使他们仍然容忍那些希望坚持其中一个极端的程序员。