Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

private functions vs nested functions

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?

like image 791
cyril.andreichuk Avatar asked Apr 07 '13 04:04

cyril.andreichuk


2 Answers

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.

like image 135
Jack P. Avatar answered Sep 28 '22 10:09

Jack P.


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.

like image 27
pad Avatar answered Sep 28 '22 09:09

pad