2008-11-22 47 views
5

我正在學習函數式編程,並試圖解決功能風格中的幾個問題。我經歷的一件事是,將我的問題分解爲函數,似乎我有兩個選擇:使用幾個具有相似參數列表的不同函數,或使用嵌套函數,它們作爲閉包,可以簡單地引用父函數中的綁定。嵌套功能:不當使用副作用?

儘管我最終採用第二種方法,因爲它使得函數調用更小,並且它似乎「感覺」更好,從我的閱讀中看,似乎我可能缺少函數式編程的一個要點,這似乎是「副作用」?現在被授予,這些嵌套函數不能修改外部綁定,因爲我使用的語言阻止了這種綁定,但是如果您查看每個單獨的內部函數,則不能說「給定相同的參數,此函數將返回相同的結果」因爲他們確實使用了父範圍的變量......我是對的嗎?

什麼是繼續進行的理想方式?

謝謝!

回答

2

嵌套函數是劃分許多函數中勞動力的極好方法。這不是真正的「副作用」;如果有幫助,可以將捕獲的變量看作隱式參數。

嵌套函數有用的一個示例是替換循環。嵌套函數的參數可以作爲積累值的歸納變量。一個簡單的例子:

let factorial n = 
    let rec facHelper p n = 
     if n = 1 then p else facHelper (p*n) (n-1) 
    in 
    facHelper 1 n 

在這種情況下,就沒有真正意義的聲明函數像facHelper全球範圍內,因爲用戶不應該擔心p參數。

但是,請注意,單獨測試嵌套函數可能很困難,因爲它們不能在父級之外引用。

+0

facHelper實際上並不涉及任何外部值 - 它仍然是純粹的功能。 – 2008-11-22 07:28:33

3

函數式編程不是全有或全無。如果嵌套函數更有意義,我會採用這種方法。但是,如果您確實希望內部函數具有純功能,請將所有必需的參數明確傳遞給它們。

這裏有一個小例子方案:

(define (foo a) 
    (define (bar b) 
    (+ a b))  ; getting a from outer scope, not purely functional 
    (bar 3)) 

(define (foo a) 
    (define (bar a b) 
    (+ a b))  ; getting a from function parameters, purely functional 
    (bar a 3)) 


(define (bar a b) ; since this is purely functional, we can remove it from its 
    (+ a b))  ; environment and it still works 

(define (foo a) 
    (bar a 3)) 

就個人而言,我會用第一種方法去,但無論是將工作得很好。

1

考慮以下(人爲)的Haskell片段:

putLines :: [String] -> IO() 
putLines lines = putStr string 
    where string = concat lines 

string是一個本地綁定命名常量。但是,這不是一個沒有任何關於lines關閉的參數的函數,因此它是不透明的? (在Haskell中,常量和空值函數實際上是無法區分的!)您會考慮上面的代碼是「副作用」還是非功能性的?