[   ^ to index...   |   next -->   ]

CSE 341 : 26 April 2001

Higher-order and first-class functions

A "higher-order" function is one that returns a function or takes a function as a parameter. Higher-order functions are a form of meta-programming, i.e. "code that operates on code".

"First-class functions" are orthogonal to higher-order functions. A value is first-class in a language if you can do anything with it that you can do with any other value. In ML, all data values are first class, including functions.

You do not need first class functions in order to make interesting higher order functions. Here is the qsort function from the C standard library stdlib.h:

void qsort(void *base, size_t nmemb, size_t size,
               int (*compar)(const void *, const void *));

If you get around the ugly syntax, this function takes an array (base), a number of items (nmemb), a size of each item in the array (size), and a pointer to a comparison function (compar). To use this, we would have to define a new top-level function:

int double_greater(const void *r1, const void* r2) {
    return (*(double *)r1 > *(double *)r2) ? 1 : 0;
}

double array[5] = { 1.2, 24.2, 4.2, 9.0, 17.3 };  /* usage */
qsort(array, 5, sizeof(double), double_greater);

If we're writing many higher-order functions, first class functions, polymorphic types, and nice syntax are nice to have. Consider the ML equivalent of the above:

fun qsort(greaterThan:('a * 'a) -> bool, nil:'a list):'a list = ...
val foo = [1.2, 24.2, 4.2, 9.0, 17.3];
val sorted = qsort(op >, foo);

Notice that op >, the name of the function for comparing reals (this name is overloaded on integers and strings, but ignore that for the moment), can be passed just like any other value. Here is the full definition of quicksort:

fun qsort(greaterThan:('a * 'a) -> bool, nil:'a list):'a list = nil
  | qsort(greaterThan, pivot::rest) =
    let
        fun partition(pivot, nil) = (nil, nil)
          | partition(pivot, x::xs) =
            let val (lessOrEqual, greater) = partition(pivot, xs);
            in  if greaterThan(x, pivot) then (lessOrEqual, x::greater)
                                         else (x::lessOrEqual, greater)
            end;
        val (lessOrEqual, greater) = partition(pivot, rest);
    in
        qsort(greaterThan, lessOrEqual) @ pivot::qsort(greaterThan, greater)
    end;

Keunwoo Lee
Last modified: Thu Apr 26 10:42:29 PDT 2001