7

我正在学习函数式编程,并试图以函数式风格解决几个问题。在将问题分解为函数时,我经历过的一件事是,我似乎有两个选择:使用具有相似参数列表的几个不同的函数,或者使用嵌套函数,作为闭包,可以简单地引用父函数中的绑定。

虽然我最终选择了第二种方法,因为它使函数调用更小并且似乎“感觉”更好,但从我的阅读来看,我似乎可能错过了函数式编程的要点之一,因为这似乎是“一面-有效”?现在,这些嵌套函数不能修改外部绑定,因为我使用的语言阻止了这一点,但是如果你查看每个单独的内部函数,你不能说“给定相同的参数,这个函数将返回相同的结果”因为他们确实使用了父作用域中的变量......我是对的吗?

什么是理想的进行方式?

谢谢!

4

3 回答 3

4

函数式编程不是全有或全无。如果嵌套函数更有意义,我会采用这种方法。但是,如果您真的希望内部函数是纯函数式的,请将所有需要的参数显式传递给它们。

这是Scheme中的一个小例子:

(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))

就个人而言,我会采用第一种方法,但任何一种方法都同样有效。

于 2008-11-22T06:48:29.793 回答
3

嵌套函数是在许多函数中分工的绝佳方式。这并不是真正的“副作用”;如果有帮助,请将捕获的变量视为隐式参数。

嵌套函数有用的一个例子是替换循环。嵌套函数的参数可以充当累加值的归纳变量。一个简单的例子:

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参数。

但是请注意,单独测试嵌套函数可能很困难,因为它们不能在其父函数之外引用。

于 2008-11-22T07:25:06.117 回答
1

考虑以下(人为的)Haskell 片段:

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

string是一个局部绑定的命名常量。但它不也是一个不带参数的函数,它关闭lines并因此在引用上不透明吗?(在 Haskell 中,常量和空函数确实无法区分!)您会因此认为上面的代码“有副作用”还是没有功能?

于 2008-11-22T12:17:04.717 回答