Scala与F#问题:它们如何统一OO和FP范式?
Scala和F#采用的统一OO和FP范式的方法之间的关键区别是什么 编辑 每种方法的相对优缺点是什么?如果,尽管支持子类型,F#可以推断函数参数的类型,那么为什么Scala不能呢?F#是功能性的-它很好地支持OO,但设计和原理仍然是功能性的。示例:Scala与F#问题:它们如何统一OO和FP范式?,scala,f#,functional-programming,comparison,paradigms,Scala,F#,Functional Programming,Comparison,Paradigms,Scala和F#采用的统一OO和FP范式的方法之间的关键区别是什么 编辑 每种方法的相对优缺点是什么?如果,尽管支持子类型,F#可以推断函数参数的类型,那么为什么Scala不能呢?F#是功能性的-它很好地支持OO,但设计和原理仍然是功能性的。示例: Haskell型函数 自动咖喱 自动泛型 参数的类型推断 以主要面向对象的方式使用F#感觉比较笨拙,因此可以将其主要目标描述为将OO集成到函数式编程中 Scala是一种注重灵活性的多范式。您可以根据当前最适合的方式在真实的FP、OOP和过程风格之
- Haskell型函数
- 自动咖喱
- 自动泛型
- 参数的类型推断
Scala在JVM上的工作与F在CLR上的工作类似。然而Scala选择采用更类似Java的语法。这可能有助于面向对象程序员采用它,但对于函数式程序员来说,它可能会感到有点沉重。它的对象模型类似于Java,允许与Java无缝互操作,但有一些有趣的区别,比如对traits的支持。有很多要点可以用来比较两者(或三者)。首先,我可以想到以下几点:
- 语法
在语法上,F#和OCaml基于函数式编程传统(空间分隔且更轻量级),而Scala基于面向对象风格(尽管Scala使其更轻量级) - 集成OO和FP
F#和Scala都非常顺利地将OO与FP集成在一起(因为这两者之间没有矛盾!!)您可以声明类来保存不变的数据(功能方面),并提供与数据相关的成员,还可以使用接口进行抽象(面向对象方面)。我对OCaml不太熟悉,但我认为它更强调OO方面(与F#相比) - F#中的编程风格
我认为F#中通常使用的编程风格(如果您不需要编写.NET库并且没有其他限制)可能更实用,并且您只会在需要时使用OO特性。这意味着您可以使用函数、模块和代数数据类型对功能进行分组 - Scala中的编程风格
在Scala中,默认的编程风格更面向对象(在组织中),但是您仍然(可能)编写功能性程序,因为“标准”方法是编写避免变异的代码
|>
)。请从以下站点获取此代码段:
函数map
不是列表实例的方法。相反,它的工作方式类似于列表
模块上的静态方法,该模块将列表实例作为其参数之一
另一方面,Scala完全是面向对象的。首先,让我们从该代码的Scala等价物开始:
List(1 to 10) map fib
// Without operator notation or implicits:
List.apply(Predef.intWrapper(1).to(10)).map(fib)
这里,map
是List
实例上的一个方法。类似于静态的方法,例如Predef
上的intWrapper
或List
上的apply
,要少见得多。还有一些函数,如上面的fib
。这里,fib
不是int
上的方法,但也不是静态方法。相反,它是一个对象——我看到F#和Scala之间的第二个主要区别
让我们考虑来自维基百科的F~*实现,以及等价的Scala实现:
// F#, from the wiki
let rec fib n =
match n with
| 0 | 1 -> n
| _ -> fib (n - 1) + fib (n - 2)
// Scala equivalent
def fib(n: Int): Int = n match {
case 0 | 1 => n
case _ => fib(n - 1) + fib(n - 2)
}
上面的Scala实现是一种方法,但Scala将其转换为一个函数,以便能够将其传递给map
。我将在下面对其进行修改,使其成为一个返回函数的方法,以显示函数在Scala中的工作方式
// F#, returning a lambda, as suggested in the comments
let rec fib = function
| 0 | 1 as n -> n
| n -> fib (n - 1) + fib (n - 2)
// Scala method returning a function
def fib: Int => Int = {
case n @ (0 | 1) => n
case n => fib(n - 1) + fib(n - 2)
}
// Same thing without syntactic sugar:
def fib = new Function1[Int, Int] {
def apply(param0: Int): Int = param0 match {
case n @ (0 | 1) => n
case n => fib.apply(n - 1) + fib.apply(n - 2)
}
}
因此,在Scala中,所有函数都是实现traitFunctionX
的对象,它定义了一个名为apply
的方法。如这里所示,在上面的列表创建中,.apply
可以省略,这使得函数调用看起来就像方法调用一样
最后,Scala中的所有东西都是一个对象——一个类的实例——每个这样的对象都属于一个类,所有代码都属于一个方法,该方法以某种方式执行。在上面的例子中,甚至match
也曾是一个方法,但已被转换为关键字
// F#, returning a lambda, as suggested in the comments
let rec fib = function
| 0 | 1 as n -> n
| n -> fib (n - 1) + fib (n - 2)
// Scala method returning a function
def fib: Int => Int = {
case n @ (0 | 1) => n
case n => fib(n - 1) + fib(n - 2)
}
// Same thing without syntactic sugar:
def fib = new Function1[Int, Int] {
def apply(param0: Int): Int = param0 match {
case n @ (0 | 1) => n
case n => fib.apply(n - 1) + fib.apply(n - 2)
}
}