Lambda calculus is a formal model of computation based on function abstraction and application. It provides the theoretical foundation for functional programming languages and demonstrates that all computable functions can be expressed using only variables, function definitions (λ), and function calls. Every program in lambda calculus is a reduction sequence that simplifies expressions to normal forms.
You already know what functions are — you define them, pass arguments, and get results back. Lambda calculus strips that idea down to its absolute minimum. There are exactly three things in the entire system: variables (names like x), abstractions (anonymous function definitions written λx.body, meaning "a function that takes x and returns body"), and applications (calling a function by placing it next to its argument). That's it. No numbers, no if-statements, no loops — just functions all the way down. The remarkable discovery is that this is enough to express any computation a Turing machine can perform.
Computation in lambda calculus happens through beta reduction: replacing a function's parameter with the supplied argument. For example, (λx.x+1) 3 reduces to 3+1 by substituting 3 for every x in the body. When no more reductions are possible, you've reached a normal form — the final answer. This is directly analogous to how you evaluate function calls in programming: substitute the arguments, simplify, repeat. The key subtlety is variable capture — when substituting, you must avoid accidentally binding free variables to the wrong λ, which is why formal rules for renaming (alpha conversion) exist.
What makes lambda calculus powerful as a foundation for compilers is that it reveals the essence of what programming languages do. Every language feature — conditionals, loops, data structures — can be encoded as lambda expressions. Booleans become functions that select between two arguments: TRUE = λx.λy.x (pick the first), FALSE = λx.λy.y (pick the second). Numbers become Church numerals, where the number n is a function that applies another function n times. This encoding shows that the boundary between "code" and "data" is an illusion — everything is a function.
For compiler design specifically, lambda calculus provides the formal semantics that let you reason about program transformations. When a compiler optimizes code, it needs to guarantee that the optimized version produces the same result as the original. Lambda calculus gives precise rules for when two expressions are equivalent — if one reduces to the other, they mean the same thing. This mathematical backbone underlies type systems, closure implementations, and the intermediate representations used in functional language compilers. Understanding lambda calculus means understanding computation at its most fundamental level, before any particular machine architecture or language syntax gets in the way.