the question is:
when to use private functions and when to use nested functions? (i'm asking about F# but maybe answers can be relevant in other functional languages)
a small example
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
it's a big bonus that a nested function can use data from higher scope. also it does not pollute the surrounding module. but is looks clumsy, isn't it? especially when there are some large nested functions
on opposite, private functions can be made public and be tested. and it seems that they look more readable
what's your opinion?
It's a big bonus that a nested function can use data from higher scope. also it does not pollute the surrounding module.
I agree with your points. My advice is to keep functions at the right scopes. For example, if the function is used in only one place, it's better to be a nested function. For example, there's no point to move loop
upwards and make it a private
function.
let length xs =
let rec loop acc = function
| [] -> acc
| _::xs -> loop (acc + 1) xs
loop 0 acc
But is looks clumsy, isn't it? especially when there are some large nested functions
If you need large nested functions, it's likely you're doing it wrong. They should be broken into multiple small nested functions or the outermost function should be converted to a type.
On opposite, private functions can be made public and be tested. and it seems that they look more readable.
Readability is a subjective matter. I think organization issue is more important. The points of nested functions are that they're simple and could be tested by testing outermost functions.
When functions have more applicability, you can put them into a utility module and open that module when needed. Note that there are other techniques to hide functions other than marking them private
. For example, you can use an fsi
file to indicate what interface is exposed.
I use private
functions in modules quite often -- usually for "helper" functions that are consumed by other functions in the module, but which don't need to be exposed to outside code.
One other use case for private
functions is to simply make the code more readable. If a function is nested within another function, but it gets too long to read -- e.g., if the nested function's code makes up more than half of the length of the function it's contained by -- I'll usually move it out to the module level and make it private
so the caller function's code is easier to understand.