DevLearningTools

MODULE 6 · LESSON 06

Recursion (optional)

Writing recursive functions in ColdFusion — the base case, accumulator patterns, why state doesn't persist automatically between calls, and the scoping habits that keep recursive calls from interfering with each other.

New lessons are added one at a time as the course gets built out — a graded quiz for each lesson is still on the way.

A recursive function is one that calls itself to solve a smaller version of the same problem, until it reaches a case simple enough to answer directly. It's an optional lesson — most day-to-day CFML code doesn't need it — but a few real problems (walking a category tree, flattening nested structs) are genuinely cleaner written recursively than as a manual loop.

Learning Objectives

After completing this lesson, you'll be able to:

  • Identify the base case and recursive case in a recursive function.
  • Write a simple recursive function like factorial.
  • Explain why a recursive function must pass state through arguments rather than relying on it "remembering" the previous call.
  • Avoid the two most common recursion bugs: a missing base case, and forgetting var on local variables.

The Two Parts Every Recursive Function Needs

  • A base case — a condition simple enough to return an answer directly, with no further recursive call. Without this, the function calls itself forever until the request runs out of stack space.
  • A recursive case — where the function calls itself with an input that's measurably closer to the base case than the input it received.

Classic Example: Factorial

CFScript
Simulated output — illustrative only, not a live ColdFusion/Lucee server.
Tag Syntax
Simulated output — illustrative only, not a live ColdFusion/Lucee server.

State Doesn't Persist — Pass It Through Arguments

A recursive function doesn't automatically remember anything from its previous call. Anything that needs to accumulate across calls — a running total, a growing list — has to be passed in as an argument and handed forward explicitly, usually with a default value for the first call.

CFScript
Simulated output — illustrative only, not a live ColdFusion/Lucee server.
Tag Syntax
Simulated output — illustrative only, not a live ColdFusion/Lucee server.

Real-World Example: Walking a Category Tree

A common real use of recursion: building a breadcrumb trail by walking up from a category to its parent, and its parent's parent, until there's no parent left.

CFScript
Simulated output — illustrative only, not a live ColdFusion/Lucee server.
Tag Syntax
Simulated output — illustrative only, not a live ColdFusion/Lucee server.
NOTE

The base case here is reaching category 0 ("Home"), which has no parentId — every recursive call moves one step closer to it.

Common Beginner Mistakes

Forgetting the base case, or writing one that's never actually reached

Without a reachable base case, the function keeps calling itself until it exhausts the stack and errors out. Double-check the recursive call's argument is always moving toward the base case.

Forgetting var on a recursive function's local variables

Without var, a local variable falls back to the VARIABLES scope, shared across every level of the recursion — the calls end up stomping on each other's data instead of each having its own copy.

Expecting the function to "remember" a running total on its own

It won't. Anything that needs to carry forward between calls — a sum, a collected list — has to be passed explicitly as an argument, as the accumulator pattern above does.

Best Practices

  • Write the base case first and make sure it's actually reachable before writing the recursive case.
  • Always var-scope a recursive function's local variables.
  • Reach for recursion only when the problem is naturally tree-shaped or nested — a plain loop is usually clearer (and slightly faster) for anything linear.

Interview Questions

What are the two required parts of any recursive function?

A base case that returns a result directly without recursing further, and a recursive case that calls the function again with input closer to the base case.

Why does a recursive function need to pass an accumulator as an argument?

Because a function has no memory of its previous calls — any state that needs to carry forward (a running total, a growing list) must be passed explicitly through the arguments.

What bug can happen if you forget var on a recursive function's local variables?

The variable falls back to the shared VARIABLES scope instead of being private to each call, so different levels of the recursion can overwrite each other's data.

Summary

In this lesson, you wrote recursive functions with a base case and recursive case, learned to carry state forward with an accumulator argument since recursive calls don't share memory, and covered the two bugs that catch almost everyone the first time: a missing base case, and forgetting var.

That's the whole Functions module — built-in functions, writing your own, arguments, return values, scope, and recursion.

What's Next?

The next module covers Object-Oriented Programming — components, classes vs objects, properties and methods, and the core OOP concepts (encapsulation, inheritance, polymorphism) as they work in CFML.