Search code examples
memory-managementfunctional-programminggarbage-collectionreference-countingpurely-functional

Why don't purely functional languages use reference counting?


In purely functional languages, data is immutable. With reference counting, creating a reference cycle requires changing already created data. It seems like purely functional languages could use reference counting without worrying about the possibility of cycles. Am is right? If so, why don't they?

I understand that reference counting is slower than GC in many cases, but at least it reduces pause times. It would be nice to have the option to use reference counting in cases where pause times are bad.


Solution

  • Your question is based on a faulty assumption. It's perfectly possible to have circular references and immutable data. Consider the following C# example which uses immutable data to create a circular reference.

    class Node { 
      public readonly Node other;
      public Node() { 
        other = new Node(this);
      }
      public Node(Node node) {
        other = node;
      }
    }
    

    This type of trick can be done in many functional languages and hence any collection mechanism must deal with the possibility of circular references. I'm not saying a ref counting mechanism is impossible with a circular reference, just that it must be dealt with.

    Edit by ephemient

    In response to the comment... this is trivial in Haskell

    data Node a = Node { other :: Node a }
    recursiveNode = Node { other = recursiveNode }
    

    and barely any more effort in SML.

    datatype 'a node = NODE of unit -> 'a node
    val recursiveNode : unit node =
        let fun mkRecursiveNode () = NODE mkRecursiveNode
        in mkRecursiveNode () end
    

    No mutation required.