- Abstraction
- AI Pair Programming
- Algorithm
- API
- Array
- Array methods
- Booleans
- Callback
- Class
- Class Members
- Closure
- Closure
- Code refactoring
- Comment
- Computer programming
- Conditional statements
- Constant
- Constructor
- Coupling and Cohesion
- Data types
- Debugging
- Decorator
- Dependency
- Destructuring
- Dictionary
- Enum
- Event
- Exception / Error handling
- Function
- Generic / Template
- Higher-order function
- IDE
- Immutability
- Inheritance
- Input validation
- Integer
- Interface
- Iteration patterns
- Legacy code
- Loop
- Machine learning
- Memoization
- Memory and references
- Method
- Module
- Null / Undefined / None
- Null safety / Optional values
- Object
- Object-Oriented Programming (OOP)
- Operator
- Parameter
- Parsing
- Promise and Async/Await
- Prompt Engineering
- Recursion
- Regular expression
- Return statement
- Rollback
- Runtime
- Scope
- Script
- Sequence
- Set
- Spaghetti code
- Spread and Rest operators
- State management
- String
- Switch statement
- Synchronous vs Asynchronous execution
- Syntax
- Technical debt
- Ternary operator
- Testing
- This / Self
- Tuple
- Type casting
- Type conversion
- Variable
- Vibe coding
- Webhook
PROGRAMMING-CONCEPTS
Memoization: Definition, Purpose, and Examples
Memoization is an optimization technique where a function stores the results of expensive calculations and returns the cached value when the same inputs appear again. It improves performance by avoiding repeated work, especially in tasks involving recursion, data processing, or slow operations like API calls.
Memoization works best with pure functions—functions whose outputs depend only on inputs and have no side effects—because their results are predictable and safe to reuse.
How Memoization Works
The key idea is simple:
- Check if the function has seen the input before.
- If yes, return the stored result.
- If no, compute the result, store it, and return it.
This pattern reduces time complexity dramatically in some situations, especially recursive algorithms.
A Basic JavaScript Memoization Pattern
function memoize(fn) {
const cache = {};
return function (input) {
if (cache[input] !== undefined) {
return cache[input];
}
const result = fn(input);
cache[input] = result;
return result;
};
}
This wrapper stores results inside cache, keyed by input. The next time the function is called with the same input, it returns the cached result instantly.
const square = memoize(n => n * n);
square(10); // computes
square(10); // retrieves from cache
The first call performs the multiplication, while the second is nearly instantaneous. This is a common pattern for performance-sensitive code.
React Example: useMemo
React doesn’t memoize functions automatically, but it offers useMemo() to memoize computed values inside components.
const total = useMemo(() => {
return items.reduce((sum, item) => sum + item.price, 0);
}, [items]);
React only recalculates the total when items changes. This avoids unnecessary computations during re-renders, which improves UI performance when lists grow large.
TypeScript Example (Typed Memoization)
function memoizeNumber(fn: (n: number) => number) {
const cache: Record<number, number> = {};
return (n: number): number => {
if (n in cache) return cache[n];
return (cache[n] = fn(n));
};
}
TypeScript ensures the memoized function only accepts and returns specific types. This adds safety but follows the same logic as JavaScript.
Python Example
Python developers often use dictionaries to implement memoization.
Python
def memoize(fn):
cache = {}
def wrapper(n):
if n in cache:
return cache[n]
result = fn(n)
cache[n] = result
return result
return wrapper
This function decorates another function to add caching. It’s a straightforward pattern used frequently in recursive algorithms.
Using It on a Function
Python
@memoize
def double(n):
return n * 2
The function now keeps track of previous inputs and instantly returns cached values on repeat calls. This improves performance without needing to rewrite the original logic.
Swift Example Using a Dictionary
Swift doesn’t include built-in memoization, but you can implement it manually.
func memoize<T: Hashable, U>(_ fn: @escaping (T) -> U) -> (T) -> U {
var cache: [T: U] = [:]
return { input in
if let value = cache[input] { return value }
let result = fn(input)
cache[input] = result
return result
}
}
Swift’s generics make this reusable for many types as long as the input is hashable. This lets you memoize computationally heavy functions in a clean and reusable way.
Memoization in Recursion
Memoization is especially powerful in recursive functions with overlapping subproblems, where the same values get recalculated repeatedly.
Fibonacci Without Memoization (Slow)
function fib(n) {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
}
This version recalculates the same Fibonacci values many times. Performance drops dramatically as n increases.
Fibonacci With Memoization (Fast)
const fibMemo = memoize(function fib(n) {
if (n <= 1) return n;
return fib(n - 1) + fib(n - 2);
});
The memoized version stores results for each n, turning exponential time into linear. This pattern is common in dynamic programming.
When Memoization Helps
Memoization becomes valuable when:
- the function does expensive calculation
- the same inputs occur repeatedly
- the function is pure (consistent input → consistent output)
- the cost of computing is higher than the cost of storing results
It’s especially common in:
- recursive algorithms
- data processing that revisits values
- UI frameworks (React, SwiftUI) to prevent unnecessary rework
- API logic to avoid duplicate calls
Memoization vs Caching
Memoization is a form of caching, but focused exclusively on function results.
General-purpose caching may store:
- API responses
- database queries
- file contents
- computed assets
Memoization specifically attaches the cache to a function.
Common Mistakes
Memoizing functions with side effects
If a function changes behavior over time or touches external state, memoizing it will return outdated or incorrect results.
Using objects as keys unintentionally
In JavaScript, {} !== {}, so using object inputs requires custom hashing logic.
Forgetting cache invalidation
Long-running programs may need strategies to clear old results.
Overusing memoization
Not every function benefits — sometimes the overhead outweighs the speedup.
Summary
Memoization stores the results of expensive function calls so they can be reused instantly when the same inputs appear. JavaScript and TypeScript often use higher-order functions, Python relies on dictionaries and decorators, and React offers useMemo for component performance. Applied correctly, memoization reduces repetitive computation, speeds up recursive algorithms, and helps maintain smooth UI performance.
Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.