2013-04-07 154 views
3

问题是:私有函数vs嵌套函数

何时使用私有函数以及何时使用嵌套函数? (我问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 

这是一个巨大的奖赏,即在嵌套函数可以从更高的范围内使用的数据。也不污染周围的模块。但看起来很笨拙,不是吗?特别是当有一些大的嵌套功能

相反,私人功能可以公开并被测试。看起来它们看起来更具可读性

你的意见是什么?

+1

在真正的代码中看到'let private'非常少见 - 我认为使用私有方法创建类型会比较普遍 – 2013-04-07 06:41:24

+0

我同意'let private'不是很常见,但我认为可能仅仅是因为F#的传统功能。我其实很喜欢'让私人',并发现它非常有用(当私人功能是一个独立的功能)。 – 2013-04-07 13:26:57

+1

私人模块功能的一个刺激...当试图在F#Interactive中运行它们时...我得到这个“错误FS1094:'myPrivateFunction'的值无法从此代码位置访问。我必须删除'private',将函数添加到F#Interactive中,并记得在完成时替换'private'。 – Wally 2015-03-26 18:04:13

回答

0

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

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

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

但就是看似笨拙,不是吗?特别是当有一些大的嵌套功能

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

相反,私人功能可以公开并进行测试。看起来他们看起来更具可读性。

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

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

+1

不幸的是,有些情况下你不能将函数分解成小的函数,因为那些小函数没有意义。另外我还必须补充一点,问题是关于只有作为另一个函数的一部分才有意义的函数(在我的例子中,outerFun),并不意味着它可以被模块中的其他函数重用。也许'私人'在这里是不对的。谢谢你的好回答! – 2013-04-07 12:33:45

4

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

private函数的另一个用例是简单地使代码更具可读性。如果一个函数嵌套在另一个函数中,但是它的读取时间太长 - 例如,如果嵌套函数的代码占函数长度的一半以上 - 我通常会将它移动到模块级别并使其成为private,因此调用者函数的代码更易于理解。