What lambda Creates
A lambda expression, (lambda (parameters) body), creates a function object without binding it to a name — it's the direct source of the term 'anonymous function' used across many programming languages, and LISP is where the concept originated in practical computing, drawing on Alonzo Church's lambda calculus. You can call a lambda expression immediately, as in ((lambda (x) (* x x)) 5), or more commonly pass it as a value to another function that expects a function argument, such as a sorting comparator or a mapping operation. defun itself is essentially syntactic sugar: (defun square (x) (* x x)) is roughly equivalent to binding the symbol square's function cell to (lambda (x) (* x x)).
Cricket analogy: A lambda is like a substitute fielder brought on for exactly one over with no name announced on the scoreboard — they perform the exact same fielding function as any named player, but there's no persistent roster entry, unlike a permanent squad member (a defun'd function).
((lambda (x) (* x x)) 5) ; => 25, called immediately
(mapcar (lambda (x) (* x x)) '(1 2 3 4))
; => (1 4 9 16)
(remove-if (lambda (x) (evenp x)) '(1 2 3 4 5 6))
; => (1 3 5)
(reduce (lambda (acc x) (+ acc x)) '(1 2 3 4 5) :initial-value 0)
; => 15Higher-Order Functions: mapcar, remove-if, reduce
Lambdas are most useful when passed to higher-order functions — functions that take other functions as arguments. mapcar applies a function to each element of one or more lists and collects the results into a new list, preserving order and length (when given one list). remove-if keeps only the elements for which the predicate function returns nil, discarding the rest, while remove-if-not does the inverse. reduce combines all elements of a sequence into a single accumulated value by repeatedly applying a two-argument function, optionally seeded with :initial-value, making it the tool of choice for sums, products, or building up any running aggregate.
Cricket analogy: mapcar is like applying a 'convert to strike rate' calculation across every batter's individual scorecard entry, producing a new list of strike rates one-for-one with the batting order, while reduce is like aggregating every batter's runs into a single team total.
In Common LISP, you generally don't need to quote a lambda expression with #' when passing it directly as an argument, e.g. (mapcar (lambda (x) ...) lst) works because lambda expands into a form the compiler recognizes, but when passing a named function like #'square instead of a literal lambda, the sharp-quote is required to get the function object rather than the symbol.
Closures: Lambdas That Capture Their Environment
A lambda expression is a closure: it captures the lexical environment in which it was created, including any local variables that were in scope at that point, and continues to have access to them even after the enclosing function has returned. This lets you write function factories — functions that return other functions customized by their captured arguments — such as (defun make-adder (n) (lambda (x) (+ x n))), where each call to make-adder produces a distinct closure remembering its own value of n, so (funcall (make-adder 5) 10) returns 15 while (funcall (make-adder 100) 10) returns 110, using the same lambda code but different captured environments.
Cricket analogy: A closure is like a bowler's muscle memory for a specific match situation, say bowling a yorker at the death overs against a specific batter — the skill 'remembers' the context (field placement, batter's weakness) it was trained under, and each bowler's version of that skill carries its own remembered context even though the delivery mechanics look the same.
Because each call to a factory function like make-adder creates a fresh lexical environment, closures created in a loop that naively share a single mutated loop variable can all end up capturing the same final value rather than the value at each iteration — always double-check whether your loop construct rebinds the variable freshly on each iteration (as dolist and loop typically do) before assuming each closure captured a distinct value.
- lambda creates an anonymous (unnamed) function: (lambda (params) body).
- defun is roughly equivalent to binding a symbol's function cell to a lambda expression under a given name.
- Lambdas are most commonly passed to higher-order functions like mapcar, remove-if, and reduce rather than called immediately.
- mapcar transforms each element of a list into a new list; remove-if/remove-if-not filter elements by a predicate; reduce folds a sequence into a single accumulated value.
- A lambda is a closure — it captures the lexical environment (local variables in scope) at the point it was created.
- Function factories like make-adder use closures to produce customized functions that each remember their own captured values.
- Passing a named function reference (e.g., #'square) requires the sharp-quote, whereas an inline lambda expression does not.
Practice what you learned
1. What does ((lambda (x) (* x x)) 5) evaluate to?
2. What does (mapcar (lambda (x) (* x 2)) '(1 2 3)) return?
3. What is the difference between remove-if and remove-if-not?
4. In (defun make-adder (n) (lambda (x) (+ x n))), what does (funcall (make-adder 5) 10) return?
5. What does it mean for a lambda expression to be a 'closure'?
Was this page helpful?
You May Also Like
Defining Functions in LISP
Learn how to define named functions in LISP using defun, understand parameter lists, return values, and documentation strings.
let and Local Bindings
Learn how let and let* create local variable bindings in LISP, and how their scoping rules differ from global assignment.
Recursion in LISP
Understand how recursion works in LISP, including base cases, recursive list processing, and tail-call optimization.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics