that is outside of the function's body should be passed to it, and because of that a closure needs to be built manually. Therefore we can not speak of "first-class" functions here. typedef struct { int (*f)(int, int, int); int *a; int *b; } closure_t; void map(closure_t *closure, int x[], size_t n) { for (int i = 0; i < n; ++i) x[i] = (*closure->f)(*closure->a, *closure->b, x[i]); } int f(int a, int b, int x) { return a * x + b; } void main() { int l[] = {1, 2, 3, 4, 5}; int a = 3; int b = 1; closure_t closure = {f, &a, &b}; map(&closure, l, 5); } Also note that the map is now specialized to functions referring to two ints outside of their environment. This can be set up more generally, but requires more boilerplate code. If f would have been a nested function we would still have run into the same problem and this is the reason they are not supported in C. Higher-order functions: returning functions as results When returning a function, we are in fact returning its closure. In the C example any local variables captured by the closure will go out of scope once we return from the function that builds the closure. Forcing the closure at a later point will result in undefined behaviour, possibly corrupting the stack. This is known as the upwards funarg problem. Assigning functions to variables Assigning functions to variables and storing them inside (global) datastructures potentially suffers from the same difficulties as returning functions. f :: [[Integer] -> [Integer]] f = let a = 3 b = 1 in [map (\x -> a * x + b), map (\x -> b * x + a)] Equality of functions As one can test most literals and values for equality, it is natural to ask whether a programming language can support testing functions for equality. On further inspection, this question appears more difficult and one has to distinguish between several types of function equality: Extensional equality Two functions f and g are considered extensionally equal if they agree on their outputs for all inputs (∀x. f(x) = g(x)). Under this definition of equality, for example, any two implementations of a stable sorting algorithm, such as insertion sort and merge sort, would be considered equal. Deciding on extensional equality is undecidable in general and even for functions