2011-06-27 68 views
25

我編寫了下面的代碼,它需要一堆點並使用光澤庫在屏幕上繪製它們。是更有效率的點免費代碼,還是僅僅比較簡單?

let s = blocks pes 
    pts = map (map mkPt) s {- stitches to points-} 
    lines = map Line pts {-points to lines -} 
    pict = Pictures lines {- lines to a picture -} 
    in do displayInWindow "My Window" (200, 200) (10, 10) white pict 

它工作正常,但是,有一個重複模式時對我說:函數調用鏈,每一個送入接下來的最後一個參數的結果。 所以我重構通過移除中間變量,反向排序與函數組合鏈接功能(「」)像這樣:

let pict = Pictures . (map Line) . (map $ map $ mkPt) . blocks $ pes 
       in do displayInWindow "My Window" (200, 200) (10, 10) white pict 

令人高興的是,這工作就好了。但是,我想知道如果我正在讀可讀性,或者如果我只是不習慣閱讀&書寫自由風格的代碼。另外,我如何推理此代碼?第二個版本更有效率,還是僅僅比較簡單?有什麼我可以做的風格,使其更清晰?

回答

31

幾個簡單的建議:

let pict = Pictures . (map Line) . (map $ map $ mkPt) . blocks $ pes 
in do displayInWindow "My Window" (200, 200) (10, 10) white pict 

你有一些多餘的東西,可以直接將其刪除:

let pict = Pictures . map Line . (map $ map mkPt) . blocks $ pes 
in do displayInWindow "My Window" (200, 200) (10, 10) white pict 

你不與map (map mkPt)長期避免括號,無論如何,所以得到擺脫$

let pict = Pictures . map Line . map (map mkPt) . blocks $ pes 
in do displayInWindow "My Window" (200, 200) (10, 10) white pict 

你可以wri忒多條線路組成鏈清晰:

let pict = Pictures 
     . map Line 
     . map (map mkPt) 
     . blocks $ pes 
in do displayInWindow "My Window" (200, 200) (10, 10) white pict 

do塊是多餘的,因爲它只有一個聲明,你可以定義之外將最終應用:

let displayPict = displayInWindow "My Window" (200, 200) (10, 10) white 
       . Pictures 
       . map Line 
       . map (map mkPt) 
       . blocks 
in displayPict pes 

您可以合併兩個map S:

let displayPict = displayInWindow "My Window" (200, 200) (10, 10) white 
       . Pictures 
       . map (Line . map mkPt) 
       . blocks 
in displayPict pes 

有時它也更易讀的長鏈使用逆轉組成歌劇從Control.Arrow

let displayPict = blocks 
        >>> map (Line . map mkPt) 
        >>> Pictures 
        >>> displayInWindow "My Window" (200, 200) (10, 10) white 
in displayPict pes 

但所有這些是可選的;季節你的代碼品嚐。

關於效率問題,我沒有理由認爲一旦GHC的優化器通過代碼,兩者就會有任何不同。

+4

確實,生成的代碼對於免費版本應該是相同的。沒有任何優化,點免費代碼會稍微低效,因爲它有更多的函數調用(組合)。 – augustss

+0

哇,這是美麗的,我不知道有關顛倒的組合運算符。謝謝! – nont

+1

@augustss:感謝您的確認 - 我並不確定,但重新排列都非常簡單,並且儘可能地重新排列子表達式,似乎沒有任何差異。除非差別很大,否則我傾向於不擔心「不優化」情況。依靠嚴格性分析器將'foldl'變成'foldl''使我感到不舒服。 –

4

點自由風格可以很好地清楚地表明函數只是對輸入進行一系列轉換。這真的很容易讀的東西,如:

foo = map show . doThis . doThat . etc 

因爲它看起來像典型的自由點代碼,所以有人熟悉它就能清楚地看到什麼是重要的,無噪音。與此相比,:顯然

foo x = d 
    where 
     a = etc x 
     c = doThis b 
     b = doThat a 
     d = map show c 

,這是一個有點做作,但這個想法是多餘的定義需要被讀取,爲了密切關注,以瞭解foo真的做得。是否將a用作多個輔助函數的參數?那麼b?數據是否以意想不到的方式流過這些幫助函數?在這種情況下,自由風格的意思是說:「事情只是在流水線上轉變,沒有你需要考慮的奇怪」

在其他情況下,無點式可以真正混淆事物。一般來說,這就是你什麼時候打發出來的。所以,簡潔不是唯一的目標,減少精神負擔也很重要。 (正如其他人所評論的那樣,免費樣式在優化代碼中應該不會有性能差異)。

相關問題