Scala与F#问题:他们如何统一OO和FP范式?

时间:2010-05-25 13:34:30

标签: scala f# functional-programming comparison paradigms

Scala和F#采用的方法在统一OO和FP范例方面有哪些主要区别?

修改

每种方法的相对优点和缺点是什么?如果,尽管支持子类型,F#可以推断出函数参数的类型,那为什么不能Scala?

7 个答案:

答案 0 :(得分:43)

答案 1 :(得分:14)

F#功能正常 - 它允许 OO很好,但设计和理念仍然是功能性的。例子:

  • Haskell式函数
  • 自动currying
  • 自动泛型
  • 参数的类型推断

以主要面向对象的方式使用F#感觉相对笨拙,因此可以描述将OO集成到函数式编程中的主要目标。

Scala 是一种多范式,专注于灵活性。您可以选择真正的FP,OOP和程序样式,具体取决于当前最适合的样式。这真的是关于统一OO和函数式编程

答案 2 :(得分:13)

您可以使用很多点来比较两个(或三个)。首先,我可以想到一些值得注意的要点:

  • <强>语法
    从语法上讲, F# OCaml 基于函数式编程传统(空间分离且更轻量级),而 Scala 基于面向对象风格(虽然Scala使它更轻巧)。

  • 整合OO和FP
    F# Scala 都非常顺利地将OO与FP集成(因为这两者之间没有矛盾!)您可以声明类来保存不可变数据(功能方面)并提供与使用数据相关的成员,您也可以使用接口进行抽象(面向对象的方面)。我对 OCaml 并不熟悉,但我认为它更强调OO方面(与F#相比)

  • F#中的编程风格
    我认为 F#中使用的常用编程风格(如果您不需要编写.NET库并且没有其他限制)可能更具功能性,并且您只能在使用OO功能时使用OO功能你需要。这意味着您可以使用函数,模块和代数数据类型对功能进行分组。

  • Scala中的编程风格
    在Scala中,默认的编程风格更加面向对象(在组织中),但是你仍然(可能)编写函数式程序,因为“标准”方法是编写避免变异的代码。

答案 3 :(得分:13)

  

Scala和F#采用的方法在统一OO和FP范例方面有哪些主要区别?

关键区别在于Scala尝试通过做出牺牲来混合范例(通常在FP方面),而F#(和OCaml)通常在范例之间画一条线,让程序员为每个任务在它们之间做出选择。

斯卡拉必须做出牺牲才能统一范式。例如:

  • 一流的功能是任何功能语言(ML,Scheme和Haskell)的基本特征。所有功能都是F#的一流功能。成员函数在Scala中是第二类。

  • 重载和子类型阻碍了类型推断。 F#提供了一个大的子语言,牺牲了这些OO特性,以便在不使用这些特征时提供强大的类型推断(在使用它们时需要类型注释)。 Scala在任何地方推出这些功能,以保持一致的OO,代价是各地的类型推断不良。

另一个结果是F#基于久经考验的想法,而Scala在这方面是开创性的。这是项目背后的动机的理想选择:F#是商业产品,Scala是编程语言研究。

另外,由于其选择的VM(JVM)的限制,Scala还牺牲了FP的其他核心功能,例如尾部调用优化,这是出于语用原因。这也使得Scala比FP更多OOP。请注意,有一个项目可以将Scala引入.NET,它将使用CLR进行真正的TCO。

  

每种方法的相对优点和缺点是什么?如果,尽管支持子类型,F#可以推断出函数参数的类型,那为什么不能Scala?

类型推断与以OO为中心的特征(如重载和子类型)不一致。对于重载,F#选择了类型推断而不是一致性。 Scala选择了无处不在的重载和子类型而不是类型推断。这使得F#更像OCaml,Scala更像C#。特别是,Scala不再是一种函数式编程语言,而是C#。

当然,哪个更好是完全主观的,但我个人更喜欢在一般情况下强大的类型推断所带来的巨大的简洁性和清晰度。 OCaml是一种很棒的语言,但一个痛点是缺乏运算符重载,需要程序员使用+表示整数,+.表示浮点数,+/表示有效性等等。再一次,F#选择实用主义而不是通过在数值的上下文中牺牲类型推断来实现重载,不仅在算术运算符上,而且在算术函数如sin上。 F#语言的每个角落都是经过精心挑选的务实权衡取舍的结果。尽管导致了不一致,但我相信这会使F#更有用。

答案 4 :(得分:7)

来自this关于编程语言的文章:

  

斯卡拉是一个粗犷,富有表现力的人,   严格优越的替代品   Java的。 Scala是编程   语言我会用于像这样的任务   编写Web服务器或IRC客户端。   与OCaml [或F#]相比,这是一个   功能语言   面向对象的系统嫁接到它,   Scala感觉更像是真正的混合体   面向对象和功能   编程。(即面向对象   程序员应该能够开始   立刻使用Scala,拿起来   功能部件仅限于它们   选择。)

     

我首先在POPL上了解了Scala   2006年Martin Odersky给出了一个   邀请谈谈它。当时我看到了   功能编程严格   优于面向对象   编程,所以我没有看到需要   对于融合功能的语言   和面向对象的编程。 (那   可能是因为我写回了所有内容   然后是编译器,口译员和   静态分析仪。)

     

Scala的需求没有成为   对我来说很明显,直到我写了一篇   并发HTTPD从头到尾   支持yaplet的长轮询AJAX。   为了获得良好的多核   支持,我写了第一个版本   Java的。作为一种语言,我不认为   Java就是那么糟糕,我可以享受   做得好的面向对象编程。   但是,作为一名功能性程序员,   缺乏(或不必要的冗长)   支持函数式编程   功能(如高阶函数)   当我用Java编程时,我会感激我。   所以,我给了Scala一个机会。

     

Scala在JVM上运行,所以我可以   逐步移植我现有的项目   进入斯卡拉。这也意味着Scala,   除了它自己相当大   库,可以访问整个Java   图书馆也是如此。这意味着你可以   在Scala中完成真正的工作。

     

当我开始使用Scala时,我成了   对于如何巧妙地印象深刻   功能性和面向对象的世界   混合在一起。特别是Scala   有一个强大的案例   类/模式匹配系统   解决了从我身上挥之不去的烦恼   使用标准ML,OCaml的经验   和Haskell:程序员可以决定   对象的哪些字段应该是   匹配(而不是强迫   匹配所有这些),和   变量参数是   允许的。事实上,Scala甚至允许   程序员定义的模式。我写了一个   很多操作的功能   抽象语法节点,这很好   能够只匹配   句法儿童,但仍然有   诸如注释之类的字段   或原始程序中的行。的的   案例类系统让一个人拆分   代数数据类型的定义   跨越多个文件或跨越   多个部分的同一个文件,其中   非常方便。

     

Scala也   支持明确定义的多重   通过类类设备继承   称为特质。

     

Scala还允许一个   相当程度的超载;   甚至功能应用程序和数组   更新可以重载。在我的   经验,这往往使我的   Scala程序更直观,更直观   简洁。

     

最终保存一个功能的一个功能   很多代码,与该类型相同   类在Haskell中保存代码,是   implicits。你可以想象暗示   作为错误恢复阶段的API   类型检查器。简而言之,何时   类型检查器需要一个X但得到了一个   是的,它会检查是否有   范围内的隐含函数   将Y转换为X;如果它找到一个,它   使用隐式“强制转换”。这使得   它可能看起来像你   扩展几乎任何类型   Scala,它允许更紧凑   嵌入DSL。

从上面的摘录中可以清楚地看出,Scala统一OO和FP范式的方法远远优于OCaml或F#。

HTH。

的问候,
埃里克。

答案 5 :(得分:5)

F#的语法取自OCaml,但F#的对象模型取自.NET。这为F#提供了一种轻巧而简洁的语法,这是函数式编程语言的特征,同时允许F#通过其对象模型非常顺利地与现有的.NET语言和.NET库进行互操作。

Scala在JVM上做了类似的工作,F#在CLR上做了类似的工作。然而,Scala选择采用更像Java的语法。这可能有助于面向对象程序员采用它,但对功能程序员来说,它可能会感觉有点沉重。它的对象模型类似于Java,允许与Java无缝互操作,但有一些有趣的差异,如支持特征。

答案 6 :(得分:3)

如果函数式编程意味着使用函数进行编程,那么Scala会稍微弯曲一下。在Scala中,如果我理解正确,那么您使用方法而不是函数进行编程。

当方法后面的类(以及该类的对象)无关紧要时,Scala会让你假装它只是一个函数。也许斯卡拉语言律师可以详细说明这种区别(如果它甚至是区别),以及任何后果。