7

问题是:

何时使用私有函数,何时使用嵌套函数?(我问的是F#,但也许答案可能与其他功能语言相关)

一个小例子

namespace SomeName

module BinaryReaderExt =
    open System.IO

    let seek (reader : BinaryReader) positions =
        reader.BaseStream.Seek(positions, SeekOrigin.Current) |> ignore

module Mod =
    open System.IO

    let private prFun reader:BinaryReader =
        //do something
        BinaryReaderExt.seek reader 10L


    let outerFun (stream :System.IO.Stream) =
        let reader = new System.IO.BinaryReader(stream)
        let seek = BinaryReaderExt.seek reader

        let nestedFun () =
            seek 10L
            //do something

        nestedFun()
        prFun reader

嵌套函数可以使用更高范围的数据是一个很大的好处。也不会污染周围的模块。但是看起来很笨拙,不是吗?特别是当有一些大型嵌套函数时

相反,私有函数可以公开并进行测试。而且它们看起来更具可读性

你怎么看?

4

2 回答 2

5

private经常在模块中使用函数——通常用于模块中其他函数使用的“帮助”函数,但不需要暴露给外部代码。

函数的另一个用例private是简单地使代码更具可读性。如果一个函数嵌套在另一个函数中,但它太长而无法阅读——例如,如果嵌套函数的代码占它所包含的函数长度的一半以上——我通常会将它移到模块级别,使private调用函数的代码更容易理解。

于 2013-04-07T13:17:19.610 回答
3

嵌套函数可以使用更高范围的数据,这是一个很大的好处。也不会污染周围的模块。

我同意你的观点。我的建议是将函数保持在正确的范围内。例如,如果函数只用在一个地方,最好是嵌套函数。例如,loop向上移动并使其成为private功能是没有意义的。

let length xs =
   let rec loop acc = function
      | [] -> acc
      | _::xs -> loop (acc + 1) xs
   loop 0 acc

但是看起来很笨拙,不是吗?特别是当有一些大型嵌套函数时

如果您需要大型嵌套函数,很可能您做错了。它们应该被分解成多个小的嵌套函数,或者最外层的函数应该转换为一种类型。

相反,私有函数可以公开并进行测试。而且它们看起来更具可读性。

可读性是一个主观问题。我认为组织问题更重要。嵌套函数的要点是它们很简单,可以通过测试最外层的函数来测试。

当函数具有更多的适用性时,您可以将它们放入实用程序模块中,并在需要时打开该模块。请注意,除了标记功能之外,还有其他技术可以隐藏功能private。例如,您可以使用fsi文件来指示公开的接口。

于 2013-04-07T09:24:58.610 回答