国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 編程設計 > 正文

深入理解Scala函數(shù)式編程過程

2020-02-02 19:00:39
字體:
來源:轉載
供稿:網友

深入理解Scala函數(shù)式編程過程

我們馬上開始一段變態(tài)的過程

如果要求立方和,可以這么做

35 * 35 * 35 68 * 68 * 68 

沒毛病,抽象一點兒,寫個函數(shù):

def cube(n: Int) = n * n * n cube(35) cube(68)

省事兒了,如果求1到10的立方和,OK,寫個遞歸

def cube(n: Int) = n * n * n  def sumCube(a: Int, b: Int): Int =    if (a > b) 0 else cube(a) + sumCube(a + 1, b)  sumCube(1, 10)

變態(tài)一點兒,立方和,平方和,階乘和,依舊寫出它們的函數(shù)并且依次計算沒毛病

def cube(n: Int) = n * n * n def id(n: Int) = n def square(n : Int) = n * n def fact(n: Int): Int =   if (n == 0) 1 else n * fact(n - 1)  def sumCube(a: Int, b: Int): Int =   if (a > b) 0 else cube(a) + sumCube(a + 1, b)  def sumSquare(a: Int, b: Int): Int =   if(a > b) 0 else square(a) + sumSquare(a + 1, b)   def sumFact(a: Int, b: Int): Int =   if (a > b) 0 else fact(a) + sumFact(a + 1, b)  def sumInt(a: Int, b: Int): Int =   if(a > b) 0 else id(a) + sumInt(a + 1, b)    sumCube(1, 10)  sumInt(1, 10)  sumSquare(1, 10)  sumFact(1, 10)

然后你發(fā)現(xiàn),你已經寫了一堆同樣邏輯的if else,看起來不奇怪么,這種無腦的操作當然要避免:

我們要把這些函數(shù)名不同但是處理邏輯相同的渣渣都封裝到一個函數(shù)中,并且這個函數(shù)將作為參數(shù)賦值到高階函數(shù)中,運行的結果只跟傳入的參數(shù)類型有關系,也就是把cube,square,fact,泛化成一個f

def cube(n: Int) = n * n * n def id(n: Int) = n def square(n : Int) = n * n def fact(n: Int): Int =   if (n == 0) 1 else n * fact(n - 1) //高階函數(shù)def sum(f: Int=>Int, a:Int, b:Int): Int =   if(a>b) 0 else f(a)+sum(f, a+1, b)// 使用高階函數(shù)重新定義求和函數(shù)def sumCube(a: Int, b: Int): Int = sum(cube, a, b) def sumSquare(a: Int, b: Int): Int = sum(square, a, b) def sumFact(a: Int, b: Int): Int = sum(fact, a, b) def sumInt(a: Int, b: Int): Int = sum(id, a, b)   sumCube(1, 10)  sumInt(1, 10)  sumSquare(1, 10)  sumFact(1, 10)

但是這樣寫,還有個問題,就是前面定義了一堆cube,id的初始定義,后面還要繼續(xù)定義,實際上就是套了一層包裝,不要了,去掉,使用匿名函數(shù)的功能來將調用進一步簡化。多數(shù)情況下,我們關心的是高階函數(shù),而不是作為參數(shù)傳入的函數(shù),所以為其單獨定義一個函數(shù)是沒有必要的。值得稱贊的是 Scala 中定義匿名函數(shù)的語法很簡單,箭頭左邊是參數(shù)列表,右邊是函數(shù)體,參數(shù)的類型是可省略的,Scala 的類型推測系統(tǒng)會推測出參數(shù)的類型。使用匿名函數(shù)后,我們的代碼變得更簡潔了:

//保留邏輯較為復雜的函數(shù)def fact(n: Int): Int = if (n == 0) 1 else n * fact(n - 1)  def sum(f: Int => Int, a: Int, b: Int): Int =   if (a > b) 0 else f(a) + sum(f, a + 1, b)  // 使用高階函數(shù)重新定義求和函數(shù)def sumCube(a: Int, b: Int): Int = sum(x => x * x * x, a, b) def sumSquare(a: Int, b: Int): Int = sum(x => x * x, a, b) def sumFact(a: Int, b: Int): Int = sum(fact, a, b) def sumInt(a: Int, b: Int): Int = sum(x => x, a, b)  sumCube(1, 10) sumInt(1, 10) sumSquare(1, 10) sumFact(1, 10)

寫到這里問題解決的差不多了,但是我們仔細想想,函數(shù)式編程的真諦,一個輸入到另一個輸出,而不是像這樣兩個參數(shù)傳來傳去,看起來很麻煩,于是乎

def fact(n: Int): Int = if (n == 0) 1 else n * fact(n - 1)  // 高階函數(shù)def sum(f: Int => Int): (Int, Int) => Int = {   def sumF(a: Int, b: Int): Int =    if (a > b) 0 else f(a) + sumF(a + 1, b)    sumF } // 使用高階函數(shù)重新定義求和函數(shù)def sumCube: Int = sum(x => x * x * x) def sumSquare: Int = sum(x => x * x) def sumFact: Int = sum(fact) def sumInt: Int = sum(x => x)  // 這些函數(shù)使用起來還和原來一樣 ! sumCube(1, 10) sumInt(1, 10) sumSquare(1, 10) sumFact(1, 10)

實際上這個時候sum里面?zhèn)魅氲囊呀浭悄涿瘮?shù)了,類似于g(f(x))里面的f(x), 你還需要去調用那個f(x)而不是去腦補運算.

我們再來開一下腦洞,既然sum返回的是一個函數(shù),我們可以直接使用這些函數(shù),沒有必要再重復寫一遍調用命令了,sumCube(1, 10) 類的語句可以省去不要了。

def fact(n: Int): Int =   if (n == 0) 1 else n * fact(n - 1)  // 高階函數(shù)def sum(f: Int => Int): (Int, Int) => Int = {   def sumF(a: Int, b: Int): Int =    if (a > b) 0 else f(a) + sumF(a + 1, b)   sumF }// 直接調用高階函數(shù) ! sum(x => x * x * x) (1, 10) //=> sumCube(1, 10) sum(x => x) (1, 10)      //=> sumInt(1, 10) sum(x => x * x) (1, 10)   //=> sumSquare(1, 10) sum(fact) (1, 10)       //=> sumFact(1, 10)

最后我們還可以使用高階函數(shù)的語法糖來進一步優(yōu)化這段代碼: 

// 沒使用語法糖的 sum 函數(shù) def sum(f: Int => Int): (Int, Int): Int = {  def sumF(a: Int, b: Int): Int =   if (a > b) 0 else f(a) + sumF(a + 1, b)   sumF } // 使用語法糖后的 sum 函數(shù) def sum(f: Int => Int)(a: Int, b: Int): Int =  if (a > b) 0 else f(a) + sum(f)(a + 1, b)

我反而覺得用語法糖更容易理解一點,更傾向于我們學的數(shù)學語言。

讀者可能會問:我們把原來的sum函數(shù)轉化成這樣的形式,好處在哪里?答案是我們獲得了更多的可能性,比如剛開始求和的上下限還沒確定,我們可以在程序中把一個函數(shù)傳給sum, sum(fact)完全是一個合法的表達式,待后續(xù)上下限確定下來時,再把另外兩個參數(shù)傳進來。對于 sum 函數(shù),我們還可以更進一步,把 a,b 參數(shù)再轉化一下,這樣 sum 函數(shù)就變成了這樣一個函數(shù):它每次只能接收一個參數(shù),然后返回另一個接收一個參數(shù)的函數(shù),調用后,又返回一個只接收一個參數(shù)的函數(shù)。這就是傳說中的柯里化,多么完美的形式!在現(xiàn)實世界中,的確有這樣一門函數(shù)式編程語言,那就是 Haskell,在 Haskell 中,所有的函數(shù)都是柯里化的,即所有的函數(shù)只接收一個參數(shù)!

// 柯里化后的 sum 函數(shù) def sum(f: Int => Int)(a: Int) (b: Int): Int = if (a > b) 0 else f(a) + sum(f)(a + 1)(b)  // 使用柯里化后的高階函數(shù) !  sum(x => x * x * x)(1)(10) //=> sumCube(1, 10)  sum(x => x)(1)(10)      //=> sumInt(1, 10) 

如有疑問請留言或者到本站社區(qū)交流討論,感謝閱讀希望能幫助到大家,謝謝大家對本站的支持!

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 麻江县| 肇东市| 云梦县| 广元市| 渭南市| 瑞丽市| 夏津县| 阿鲁科尔沁旗| 鄂托克旗| 确山县| 习水县| 曲松县| 朝阳市| 浙江省| 齐齐哈尔市| 西宁市| 阿鲁科尔沁旗| 平罗县| 耒阳市| 安国市| 东乌珠穆沁旗| 涿鹿县| 醴陵市| 朔州市| 衡南县| 罗定市| 屏东市| 抚州市| 台州市| 隆昌县| 曲阜市| 温泉县| 阿荣旗| 凤台县| 温州市| 隆尧县| 贵定县| 武邑县| 陵水| 龙州县| 青铜峡市|