- 1932: Alonzo Church develops the (type-free) Lambda Calculus as part of a general theory of functions and logic, intended as a foundation for mathematics. The whole system was proved inconsistent by Kleene and Rosser, but the Lambda Calculus (taken alone) was proved consistent.
- 1936: Kleene proves that all recursive functions can be represented in the Lambda Calculus.
- 1937: Turing proves that every function computable by a Turing machine can be represented in the Lambda Calculus, and viceversa.
- In the same years, Church formulates the statement which is
known as
*Church's Thesis*: These systems (Lambda Calculus, Turing machines, Recursive functions, and other proposed formalisms) characterize the notion of*computability*. Namely, every function which can ever be computed algoritmically can be defined in any of these systems. This statement cannot be proved, of course, because the notion of "algoritmic computability" is not defined formally. Actually, this statement can better be understood as a proposal for the definition of this notion. - Based on the Lambda Calculus, a class of programming languages have been developed: the so-called Functional Languages (Lisp, Scheme, ML, Askell, ...)

- Abstraction: if M = M[x] is an expression depending on x,
then \x.M[x] denotes the mapping x |-> M[x].
Namely the function that, for each term x, gives the term M[x].
The symbol "\" stands for the Greek letter lambda.
Example (assuming a language enriched with numerical constant and primitive operations): (\x. x+1) represents the function which, on input x, outputs x+1.

- Application: M N represents the function M applied to the argument N.

Variables: V ::= x | y | z | ...

Lambda-Terms: M ::= V | (\V M) | (M M)

M_{1}M_{2}... M_{k}stands for ( ... (M_{1}M_{2}) ... M_{k})

\x_{1}x_{2}... x_{k}.M stands for (\x_{1}(\x_{2}... (\x_{k}M) ... ))

FV(x) = {x}

FV(\x.M) = FV(M) - {x}

FV(M N) = FV(M) union FV(N)

\x.M =provided that y is neither free nor bound in M._{alpha}\y.M[y/x]

x[N/x] = N

y[N/x] = y

(\y.M)[N/x] = \x.M[N/x]

(M P)[N/x] = (M[N/x])(P[N/x])

The condition "N does not contain free variables which occur bound in M" is meant to avoid "variable capture". For example, given M = \y.zx, and N = y, if we simply replaced x by N in M, we would obtain the term \y.zy, which is intuitively incorrect since y, which was free in N, would become bound in M[N/x]. (Or in other words, M was constant on y and would become not constant.)

Variable assumption: To avoid the problems related to the "variable capture", we will assume that the free variables are different from the variables which occur bound. Note that this assumption is not restrictive since we can always alpha-rename the bounded variables. Another solution would be to define the notion of substitution so that it renames the variables automatically when needed. For this approach see for instance Hindley and Seldin, Definition 1.1.

(\x.M) N =where the variable convention is adopted so to avoid variable capture._{beta}M[N/x]

Example: (\x. x+1) 5 =_{beta} 5+1 = 6

- M = N => M P = N P (Congruence 1)
- M = N => P M = P N (Congruence 2)
- M = N => \x.M = \x.N (Xi rule)