Search code examples
functional-programmingclojure

What is the difference between functions and data?


In functional programming, we tend to distinguish between data and functions, but what is the difference?

If I consider a constant, I could think of it as a function, which just returns the same value:

(def x 5)

So what is the distinction between data and a function? I fail to see the difference.


Solution

  • Data

    • Data is a value (with a specific type).

      • For example, 5 is a value of type Integer, and "abc" is a value of type String. A composite value such as [5 "abc"] has the type Vector.

      • Two data values of the same type can always be compared for equality.

    • Data is never executed. That is, the thread of control (aka program counter or PC) never enters the data structure.

    Function (aka "code")

    • A function's only type is "code".

      • Two functions are never equal, even if they are duplicates of each other.
    • A function produces a value (with a specific type) when it is executed (possibly with arguments).

      • Execution means the thread of control enters the code data structure. The code and data values encountered there have complete control over any side-effects that occur, as well as the return value.

      • Both compiled and interpreted code produce the same results. The only difference between them are implementation details that trade off complexity vs speed.

    Eval

    • The (eval ...) special form accepts data as input and returns a function as output. The returned function can be executed (i.e. invoked) so the thread of control enters the function.

      • For clarity, the above elides details such as the reader, etc.

      • Macros are best viewed as a compiler extension embedded within the code, and do not affect the data vs code distinction.


    P.S.

    It occurred to me that the original question has not been fully answered. Consider the following:

    ; A Clojure Var pointing to the value 5
    (def five 5)
    
    ; A Clojure Var pointing to a function that always returns the value 5
    (def ->five  (fn [& args] 5))
    

    and then use these 2 Vars:

    five      => 5
    (->five)  => 5
    

    The parentheses make all the difference.

    See also: