Scala vs F#:函数式编程特性大比拼(一)

原创
开发 后端 开发工具
本文是51CTO独家译稿,讲述Scala和F#函数式编程特性对比。Scala是一种基于Java的通用编程语言,它编译成Java字节码,在Java虚拟机(JVM)上运行。F#是由微软主持开发的一个通用编程语言,它的面向对象和命令式特性大部分都与.NET平台兼容。

【51CTO独家译文】我们喜欢把.NET和Java拿出来进行比较:从测试速度安全性,从平台之争应用广泛性。而Scala和F#都是相对较新的编程语言,相对于.NET和Java编程语言,它们提供了许多非常吸引人的函数式编程特性,值得.NET和Java开发人员仔细玩味和评估。

Scala是一种基于Java的通用编程语言,旨在推广函数式编程,它编译成Java字节码,在Java虚拟机(JVM)上运行。虽然Scala本质上是一个函数式编程语言,但它也体现了面向对象语言的所有必要元素,这一点使函数式编程特性对编程社区的吸引力更大。

[[12664]]
51CTO编辑推荐:Scala编程语言专题

F#是由微软主持开发的一个通用编程语言,它是.NET通用运行时(CLR)的一部分,它是以另一个正统的函数式编程语言Ocaml为基础的,微软在.NET平台中引入F#除了人们对函数编程的兴趣不断上升外,另一个重要的原因是函数编程非常适合高性能和并行计算。虽然它的语法清晰,但F#实际上混合了函数式编程语言,命令式语言和面向对象语言的语法特性,它的面向对象和命令式特性大部分都与.NET平台兼容,F#的三重性质也很实用,它允许程序员使用任意结合这三个编程语言的特性使用。

[[12665]]
51CTO编辑推荐:F#函数式编程语言专题

本文将对Scala和F#功函数编程语法和相关特性进行对比,看看它们之间有何异同点。

一等函数

Scala和F#中的函数被视为一等类型,它们可以作为参数传递,从其它函数返回值,或分配给一个变量。

在下面的F#代码片段中,我首先定义了一个函数(increment),给传递来的值加1,然后,我定义了函数handler,它使用类型myfunc,使用2作为它的参数,最后,我使用一个递增的参数调用这个函数处理程序,函数increment作为一个有规则的值传递,因此它被认为是一等类型。

  1. let increment xx = x + 1  
  2. let handler myfunc = (myfunc 2)     
  3. printfn "%A" (handler increment)  
  4.  

注意上述代码中的类型推断,F#将会推断x是一个整型(int),因为我给它加了1,下面是使用Scala语法编写的代码:

  1. def increment(x:Int) = x + 1  
  2. def handler( f:Int => Int) = f(2)  
  3. println( handler( increment ))  
  4.  

懒散式赋值

F#支持懒散式赋值(lazy evaluation),但由于性能原因,这项特性默认并没有开启,相反,F#支持所谓的主动赋值(eager evaluation),用关键字lazy明确标记函数为懒散函数,运行程序时指定Lazy.fore选项。

  1. let lazylazyMultiply = lazy ( let multiply = 4 * 4  )  
  2.  

和F#一样,Scala默认也不支持懒散赋值,但和F#不一样的是,Scala是用lazy关键字标记值,而不是标记函数。

  1. def lazyMultiply(x: => y:) = { lazy val y = x * x }  
  2.  

#p#

局部套用函数

局部套用函数是函数式编程语言的基本功能,允许应用程序的部分函数和操作组合,F#支持局部套用函数,下面是F#中局部套用函数的一个示例。

声明:

  1. val add : int -> int -> int  
  2.  

实现:

  1. let add = (fun x -> (fun y -> x + y) )  
  2.  

在Scala中,局部套用函数的样子有所不同:

  1. def add(x:Int)(y:Int) = x + y  
  2.  

Lambda表达式

F#也支持Lambda表达式(匿名函数),在F#中,Lambda表达式是使用关键字fun声明的,在下面的例子中,一个匿名函数应用给一串递增的数字,返回一串新的递增数字。

  1. let list = List.map (fun i -> i + 1) [1;2;3]   
  2. printfn "%A" list  
  3.  

Scala中的Lambda表达式非常时尚简洁,下面是用Scala语法重写的代码:

  1. val list = List(1,2,3).map( x => x + 1 )   
  2. println( list )  
  3.  

模式匹配

模式匹配是函数式编程语言的一个强大功能,可根据值或表达式的类型激活函数中的代码块(可将模式匹配看作是功能更强大的case语句)。

在F#中,使用垂直分隔符(|)表示一个case选择器,下面是Fibonacci(斐波纳契)数字函数的F#实现。

  1. let rec fib n =  
  2.      match n with  
  3.      | 0 -> 0  
  4.      | 1 -> 1  
  5.      | 2 -> 1  
  6.      | n -> fib (n - 2) + fib (n - 1)  
  7.  

和F#一样,Scala也支持模式匹配,下面是Fibonacci(斐波纳契)数字函数的Scala实现,注意Scala使用了case关键字。

  1. def fib( n: Int): Int = n match {  
  2.     case 0 => 0  
  3.     case 1 => 1  
  4.     case _ => fib( n -1) + fib( n-2)  
  5.   }  
  6.  

列表推导

最初出现在Haskell(另一个函数式编程语言原型)中,列表推导是数学术语,使用基于符号的表达式定义列表,例如,在Haskell中,使用以下列表推导生成一串只包含大于2的数字的平方值。

  1. squares = [ x*x | x <- nums, x > 2 ]  
  2.  

F#中与列表推导相同的功能叫做发生器,它既可用于列表也可用于序列,在函数式编程语言中,序列与列表类似,但序列中的元素是在请求时才计算出来的(如,1…1000),存储效率更好。

列表发生器的格式如下:

  1. [for x in collection do ... yield expr]  
  2.  

序列发生器的格式如下:

  1. seq {for x in collection do ... yield expr}  
  2.  

因此前面的Haskell列表推导示例用F#语法重写后,就应该是:

  1. del list = [for x in 0..100 if x > 2 do yield x*x]  
  2.  

在Scala中,列表推导的结构如下:

  1. val type = for ( range ) [if (condition)] ) yield result  
  2.  

下面是用Scala语法重写后的版本:

  1. val list = for (i <- 1 to 100; if (i > 2)) yield i*i  
  2.  

通过混合实现多重继承

F#和Scala之间一个最明显的区别是F#不支持多重继承,在Scala中,程序员可以从主类声明子类扩展,也可以继承其它类的特性。

在所谓的混合类中,子类通过mixin继承,在下面的例子中,OtherParentClass就被用作mixin。

  1. Class MixinSubclass extends BaseClass with OtherParentClass  
  2.  

基类使用extends关键字声明,混合则使用with关键字声明。

继承的方法使用关键字override明确覆盖以防发生意外。

  1. override def calculate(dx: Int, dy: Int): Distance =  
  2.     new Distance(x + dy, y + dy )  
  3.  

OtherParentClass应该使用关键字trait声明:

  1. trait OtherParentClass  
  2.       def count:Int  
  3.       def kmDistance = count * 1.66  
  4.  

小结

除了Scala混合功能外,F#和Scala提供的功能都很相似,它们都非常灵活,都是很强大的函数式编程语言,本文只对这两个编程语言最基本的编程功能做了简略的比较,在下一篇文章中,我将会比较它们的最大不同点:应用程序开发模型和运行时功能。

原文出处:www.developer.com/features

原文名:Scala vs. F#: Comparing Functional Programming Features

作者:Edmon Begoli

【51CTO译稿,非经授权谢绝转载,合作媒体转载请注明原文出处、作者及51CTO译稿和译者!】

【编辑推荐】

  1. Scala vs F#:函数式编程特性大比拼(二)
  2. Scala:Java+函数式=后函数式?
  3. F#终于支持Silverlight 4 四大新特性一览
  4. Scala代码编写中常见的十大陷阱
  5. F#中关于代理的基本使用
  6. 最容易令初学者混乱的F#命令

 

责任编辑:杨鹏飞 来源: 51CTO独家译文
相关推荐

2010-07-09 14:12:00

ScalaF#C#

2010-01-07 10:04:18

F#函数式编程

2009-02-06 14:26:37

UbuntuVistaWindows7

2011-06-09 09:52:41

F#

2010-03-18 14:54:46

主流无线技术

2011-12-06 09:55:03

Ubuntu vs.F性能测试

2011-01-19 11:10:30

2018-06-08 11:05:00

2021-03-02 09:00:00

开源框架技术

2010-08-25 16:12:34

职场

2010-09-08 15:41:28

SIP协议栈

2017-09-10 14:29:03

眼力

2010-05-28 11:09:51

SVN功能

2014-01-07 17:08:02

Java开源框架

2023-05-26 15:53:48

MidjourneyAI图像

2021-03-15 21:07:17

IT行业薪酬薪水

2011-11-08 10:29:44

2010-07-14 13:38:51

Perl开发工具

2020-08-04 17:06:40

Merging Rebasing Git

2010-06-01 14:39:15

NoSQL
点赞
收藏

51CTO技术栈公众号