Search code examples
functional-programmingfortranprogramming-languagesfortran90paradigms

Is Fortran a purely functional language?


I understand that some languages combine elements for many different paradigms in programming. I'm told that Fortran is an example of a Functional language, however I'm just a little confused as to whether or not it is purely functional, as it seems to mostly be used for mathematical functions, however I also read that it is possible to apply object oriented programming to Fortran as well, so is it some sort of a hybrid?


Solution

  • "I'm just a little confused as to whether or not it is purely functional, as it seems to mostly be used for mathematical functions"

    This seems to be a misconception about the meaning of the term "purely functional", and possibly also a misconception about the meaning of the term "mathematical function".

    Mathematical functions

    A mathematical function is a mapping between inputs and outputs:

    In mathematics, a function is a relation between sets that associates to every element of a first set exactly one element of the second set.

    In the context of programming languages, the input to a function is its arguments, and the output is its return value, so e.g. a function like

    def greeting(name):
        return 'Hello, ' + name
    

    in Python is considered a mathematical function, whereas a function like

    def print_square(x):
        print(x ** 2)
        return None
    

    is not considered a mathematical function. Note here that whether or not the computation is mathematical in nature is not relevant to whether it is a function in the mathematical sense; print_square does some arithmetic, which is more like mathematics than what greeting does. But greeting is a mathematical function and print_square is not.

    greeting is a mathematical function because it is a mapping from the set of strings to the set of strings, and the function can be described by what inputs are associated with what outputs. It would take infinitely many lines to write out the mapping in full, but the mapping is like:

    'Alice'   → 'Hello, Alice'
    'Bob'     → 'Hello, Bob'
    'Charles' → 'Hello, Charles'
    '####'    → 'Hello, ####'
    ''        → 'Hello, '
    ...
    

    Every element in the first set (i.e. the set of all strings) is associated with exactly one element in the second set, so greeting meets the definition of a mathematical function.

    In contrast, print_square is not a mathematical function in the sense that it cannot be described by a mapping from inputs to outputs:

    12 → None
    4  → None
    ...
    

    These mappings (from the set of integers to the set {None}) do not properly define what print_square does, which is that it computes the square of the input and prints it to the console.

    To avoid any confusion with "functions that do something mathematical", it is better to use the computing term "pure function":

    ... a pure function is a computational analogue of a mathematical function.

    So to address your comment that Fortran "seems to mostly be used for mathematical functions", Fortran is mostly used for doing mathematical computations, but this is not what "mathematical function" means.

    Purely functional programming

    A purely functional programming language is one where all computation is done by pure functions:

    In computer science, purely functional programming usually designates a programming paradigm ... that treats all computation as the evaluation of mathematical functions. Purely functional programming may also be defined by forbidding changing-state and mutable data.

    Note that it is not sufficient for a programming language to allow you to write pure functions; this definition says all computation has to be done by pure functions for the language to qualify as purely functional.

    Is Fortran a purely functional language? No, it is not. Subroutines in Fortran can do things other than return values according to a mapping between input and output; and computations in Fortran can be done with state changes and mutable data. One example is sufficient: this one comes from Rosetta Code.

    subroutine hs(number, length, seqArray)
      integer, intent(in)  :: number
      integer, intent(out) :: length  
      integer, optional, intent(inout) :: seqArray(:)
      integer :: n
     
      n = number
      length = 1
      if(present(seqArray)) seqArray(1) = n
      do while(n /= 1)
        if(mod(n,2) == 0) then
          n = n / 2
        else
          n = n * 3 + 1
        end if
        length = length + 1
        if(present(seqArray)) seqArray(length) = n
      end do
    end subroutine
    

    The variable n is clearly mutable, as its state is changed within a loop. Also, the array seqArray is mutable, it is both an input and an output to the subroutine, and the subroutine changes the array's state. So this subroutine does not define a pure function, and it uses "changing-state and mutable data", which is forbidden by the definition of a purely functional language.

    So the subroutine hs does not define a "mathematical function", even though the computation it performs is mathematical in nature.

    Imperative programming

    Imperative programming is:

    ... a programming paradigm that uses statements that change a program's state. ... an imperative program consists of commands for the computer to perform.

    The Fortran subroutine shown above meets both of these definitions: it uses statements or commands that change the program's state, which the computer performs. So Fortran is an imperative programming language.

    Note that unlike Wikipedia's definition for "purely functional", a language can be imperative even if it doesn't do all computation in this way. So although it's possible to write pure functions in Fortran which don't work by changing the program's state, Fortran is imperative; just perhaps not "purely imperative".

    "What" vs. "How"

    "That would mean that fortran only describes the 'how' to do something and not 'what' it's trying to do?"

    It's often said that an imperative program is one which says "how" a computation should be done, whereas a declarative program only says "what" should be done. Even Wikipedia says so:

    Imperative programming focuses on describing how a program operates.

    The term is often used in contrast to declarative programming, which focuses on what the program should accomplish without specifying how the program should achieve the result.

    So is the Fortran code describing "how" the program should do something, or "what" it should accomplish?

    A statement like n = n / 2 is a command telling the computer to do something; there is a program state before the computer performs the command, and a different program state afterwards. The statement n = n / 2 also tells the computer "how" to perform the command: divide the current value of n by 2, and store the result in the variable n. So according to the "how"/"what" distinction, Fortran is imperative, not declarative.

    But you might argue: n = n / 2 says "what" we want to achieve; a new program state where n holds its value from the old state, divided by 2. And you would be right, it does say that, at least to a human reading it.

    What this shows is that the "how"/"what" distinction is too vague to be used as a definition to decide whether a language is imperative or declarative. It is meant as a loosely-described contrast between those paradigms, not as a definition of either paradigm. To decide whether a language is imperative or purely functional, or in any other paradigm, you should refer to a serviceable definition of that paradigm.