Scala vs F#:函數(shù)式編程特性大比拼(一)
原創(chuàng)【51CTO獨家譯文】我們喜歡把.NET和Java拿出來進(jìn)行比較:從測試速度到安全性,從平臺之爭到應(yīng)用廣泛性。而Scala和F#都是相對較新的編程語言,相對于.NET和Java編程語言,它們提供了許多非常吸引人的函數(shù)式編程特性,值得.NET和Java開發(fā)人員仔細(xì)玩味和評估。
Scala是一種基于Java的通用編程語言,旨在推廣函數(shù)式編程,它編譯成Java字節(jié)碼,在Java虛擬機(jī)(JVM)上運行。雖然Scala本質(zhì)上是一個函數(shù)式編程語言,但它也體現(xiàn)了面向?qū)ο笳Z言的所有必要元素,這一點使函數(shù)式編程特性對編程社區(qū)的吸引力更大。
51CTO編輯推薦:Scala編程語言專題
F#是由微軟主持開發(fā)的一個通用編程語言,它是.NET通用運行時(CLR)的一部分,它是以另一個正統(tǒng)的函數(shù)式編程語言O(shè)caml為基礎(chǔ)的,微軟在.NET平臺中引入F#除了人們對函數(shù)編程的興趣不斷上升外,另一個重要的原因是函數(shù)編程非常適合高性能和并行計算。雖然它的語法清晰,但F#實際上混合了函數(shù)式編程語言,命令式語言和面向?qū)ο笳Z言的語法特性,它的面向?qū)ο蠛兔钍教匦源蟛糠侄寂c.NET平臺兼容,F(xiàn)#的三重性質(zhì)也很實用,它允許程序員使用任意結(jié)合這三個編程語言的特性使用。
51CTO編輯推薦:F#函數(shù)式編程語言專題
本文將對Scala和F#功函數(shù)編程語法和相關(guān)特性進(jìn)行對比,看看它們之間有何異同點。
一等函數(shù)
Scala和F#中的函數(shù)被視為一等類型,它們可以作為參數(shù)傳遞,從其它函數(shù)返回值,或分配給一個變量。
在下面的F#代碼片段中,我首先定義了一個函數(shù)(increment),給傳遞來的值加1,然后,我定義了函數(shù)handler,它使用類型myfunc,使用2作為它的參數(shù),最后,我使用一個遞增的參數(shù)調(diào)用這個函數(shù)處理程序,函數(shù)increment作為一個有規(guī)則的值傳遞,因此它被認(rèn)為是一等類型。
- let increment xx = x + 1
- let handler myfunc = (myfunc 2)
- printfn "%A" (handler increment)
注意上述代碼中的類型推斷,F(xiàn)#將會推斷x是一個整型(int),因為我給它加了1,下面是使用Scala語法編寫的代碼:
- def increment(x:Int) = x + 1
- def handler( f:Int => Int) = f(2)
- println( handler( increment ))
懶散式賦值
F#支持懶散式賦值(lazy evaluation),但由于性能原因,這項特性默認(rèn)并沒有開啟,相反,F(xiàn)#支持所謂的主動賦值(eager evaluation),用關(guān)鍵字lazy明確標(biāo)記函數(shù)為懶散函數(shù),運行程序時指定Lazy.fore選項。
- let lazylazyMultiply = lazy ( let multiply = 4 * 4 )
和F#一樣,Scala默認(rèn)也不支持懶散賦值,但和F#不一樣的是,Scala是用lazy關(guān)鍵字標(biāo)記值,而不是標(biāo)記函數(shù)。
- def lazyMultiply(x: => y:) = { lazy val y = x * x }
#p#
局部套用函數(shù)
局部套用函數(shù)是函數(shù)式編程語言的基本功能,允許應(yīng)用程序的部分函數(shù)和操作組合,F(xiàn)#支持局部套用函數(shù),下面是F#中局部套用函數(shù)的一個示例。
聲明:
- val add : int -> int -> int
實現(xiàn):
- let add = (fun x -> (fun y -> x + y) )
在Scala中,局部套用函數(shù)的樣子有所不同:
- def add(x:Int)(y:Int) = x + y
Lambda表達(dá)式
F#也支持Lambda表達(dá)式(匿名函數(shù)),在F#中,Lambda表達(dá)式是使用關(guān)鍵字fun聲明的,在下面的例子中,一個匿名函數(shù)應(yīng)用給一串遞增的數(shù)字,返回一串新的遞增數(shù)字。
- let list = List.map (fun i -> i + 1) [1;2;3]
- printfn "%A" list
Scala中的Lambda表達(dá)式非常時尚簡潔,下面是用Scala語法重寫的代碼:
- val list = List(1,2,3).map( x => x + 1 )
- println( list )
模式匹配
模式匹配是函數(shù)式編程語言的一個強大功能,可根據(jù)值或表達(dá)式的類型激活函數(shù)中的代碼塊(可將模式匹配看作是功能更強大的case語句)。
在F#中,使用垂直分隔符(|)表示一個case選擇器,下面是Fibonacci(斐波納契)數(shù)字函數(shù)的F#實現(xiàn)。
- let rec fib n =
- match n with
- | 0 -> 0
- | 1 -> 1
- | 2 -> 1
- | n -> fib (n - 2) + fib (n - 1)
和F#一樣,Scala也支持模式匹配,下面是Fibonacci(斐波納契)數(shù)字函數(shù)的Scala實現(xiàn),注意Scala使用了case關(guān)鍵字。
- def fib( n: Int): Int = n match {
- case 0 => 0
- case 1 => 1
- case _ => fib( n -1) + fib( n-2)
- }
列表推導(dǎo)
最初出現(xiàn)在Haskell(另一個函數(shù)式編程語言原型)中,列表推導(dǎo)是數(shù)學(xué)術(shù)語,使用基于符號的表達(dá)式定義列表,例如,在Haskell中,使用以下列表推導(dǎo)生成一串只包含大于2的數(shù)字的平方值。
- squares = [ x*x | x <- nums, x > 2 ]
F#中與列表推導(dǎo)相同的功能叫做發(fā)生器,它既可用于列表也可用于序列,在函數(shù)式編程語言中,序列與列表類似,但序列中的元素是在請求時才計算出來的(如,1…1000),存儲效率更好。
列表發(fā)生器的格式如下:
- [for x in collection do ... yield expr]
序列發(fā)生器的格式如下:
- seq {for x in collection do ... yield expr}
因此前面的Haskell列表推導(dǎo)示例用F#語法重寫后,就應(yīng)該是:
- del list = [for x in 0..100 if x > 2 do yield x*x]
在Scala中,列表推導(dǎo)的結(jié)構(gòu)如下:
- val type = for ( range ) [if (condition)] ) yield result
下面是用Scala語法重寫后的版本:
- val list = for (i <- 1 to 100; if (i > 2)) yield i*i
通過混合實現(xiàn)多重繼承
F#和Scala之間一個最明顯的區(qū)別是F#不支持多重繼承,在Scala中,程序員可以從主類聲明子類擴(kuò)展,也可以繼承其它類的特性。
在所謂的混合類中,子類通過mixin繼承,在下面的例子中,OtherParentClass就被用作mixin。
- Class MixinSubclass extends BaseClass with OtherParentClass
基類使用extends關(guān)鍵字聲明,混合則使用with關(guān)鍵字聲明。
繼承的方法使用關(guān)鍵字override明確覆蓋以防發(fā)生意外。
- override def calculate(dx: Int, dy: Int): Distance =
- new Distance(x + dy, y + dy )
OtherParentClass應(yīng)該使用關(guān)鍵字trait聲明:
- trait OtherParentClass
- def count:Int
- def kmDistance = count * 1.66
小結(jié)
除了Scala混合功能外,F(xiàn)#和Scala提供的功能都很相似,它們都非常靈活,都是很強大的函數(shù)式編程語言,本文只對這兩個編程語言最基本的編程功能做了簡略的比較,在下一篇文章中,我將會比較它們的最大不同點:應(yīng)用程序開發(fā)模型和運行時功能。
原文出處:www.developer.com/features
原文名:Scala vs. F#: Comparing Functional Programming Features
作者:Edmon Begoli
【51CTO譯稿,非經(jīng)授權(quán)謝絕轉(zhuǎn)載,合作媒體轉(zhuǎn)載請注明原文出處、作者及51CTO譯稿和譯者!】
【編輯推薦】
- Scala vs F#:函數(shù)式編程特性大比拼(二)
- Scala:Java+函數(shù)式=后函數(shù)式?
- F#終于支持Silverlight 4 四大新特性一覽
- Scala代碼編寫中常見的十大陷阱
- F#中關(guān)于代理的基本使用
- 最容易令初學(xué)者混亂的F#命令