!Architecture Overview
Functional Programming Concepts Across Languages
Introduction
Prerequisites
| Requirement | Details |
|---|---|
| Basic setup and tooling | Basic setup and tooling |
Figure: Code pattern examples for functional programming concepts across languages—syntax comparison, idiomatic approaches, performance characteristics, and common pitfalls.
Figure: Best practices implementation for functional programming concepts across languages—error handling, testing strategies, maintainability patterns, and documentation standards.
Figure: Production readiness checklist for functional programming concepts across languages—logging, monitoring, performance tuning, and security hardening.
Functional programming emphasizes immutability, pure functions, and declarative code over imperative loops and state mutations. This guide covers core concepts—immutability, pure functions, higher-order functions, composition, closures, recursion, and monads—with practical examples in JavaScript, Python, C#, and TypeScript.
Immutability
Why Immutability Matters
Problems with mutable state:
// JavaScript: Mutable state causes bugs
let users = [
```json
{ id: 1, name: "Alice", role: "admin" },
{ id: 2, name: "Bob", role: "user" }```
];
function promoteUser(users, userId) {
```javascript
const user = users.find(u => u.id === userId);
user.role = "admin"; // ❌ Mutates original array
return users;```
}
const updatedUsers = promoteUser(users, 2);
console.log(users[1].role); // "admin" - original modified!
Immutable approach:
// ✅ JavaScript: Return new array
function promoteUser(users, userId) {
```javascript
return users.map(user =>
user.id === userId
? { ...user, role: "admin" } // New object
: user // Keep original
);```
}
const updatedUsers = promoteUser(users, 2);
console.log(users[1].role); // "user" - unchanged
console.log(updatedUsers[1].role); // "admin"
Immutable Data Structures
JavaScript/TypeScript:
// Object spread for shallow copy
const original = { name: "Alice", age: 30 };
const updated = { ...original, age: 31 };
// Array spread
const numbers = [1, 2, 3];
const extended = [...numbers, 4, 5];
// Nested immutable update
interface User {
```yaml
name: string;
address: {
city: string;
zip: string;
};```
}
const user: User = {
```yaml
name: "Alice",
address: { city: "New York", zip: "10001" }```
};
// Update nested property immutably
const updatedUser: User = {
```text
...user,
address: {
...user.address,
city: "Boston"
}```
};
// Using Immer library for complex updates
import produce from "immer";
const newUser = produce(user, draft => {
```text
draft.address.city = "Boston"; // Looks mutable but creates new object```
});
Python:
# Tuples are immutable
coordinates = (40.7128, -74.0060)
## coordinates[0] = 41 # TypeError: tuple doesn't support item assignment
![coordinates[0] = 41 # TypeError: tuple doesn't support item assignment](/images/articles/programming-languages/2025-04-07-functional-programming-concepts-across-languages-sec5-troubleshooting.jpg)
## Immutable data with dataclasses
from dataclasses import dataclass, replace
@dataclass(frozen=True) # frozen=True makes immutable
class User:
```yaml
name: str
age: int
email: str
user = User(name="Alice", age=30, email="alice@contoso.com")
user.age = 31 # FrozenInstanceError
Create modified copy
updated_user = replace(user, age=31) print(user.age) # 30 - unchanged print(updated_user.age) # 31
Immutable collections
from typing import FrozenSet
allowed_roles: FrozenSet[str] = frozenset(["admin", "user", "guest"])
allowed_roles.add("superuser") # AttributeError
**C#:**
```csharp
// Immutable record types (C# 9+)
public record User(string Name, int Age, string Email);
var user = new User("Alice", 30, "alice@contoso.com");
// user.Age = 31; // Compile error: init-only property
// Create modified copy with 'with' expression
var updatedUser = user with { Age = 31 };
Console.WriteLine(user.Age); // 30 - unchanged
Console.WriteLine(updatedUser.Age); // 31
// Immutable collections
using System.Collections.Immutable;
var numbers = ImmutableList.Create(1, 2, 3);
var extended = numbers.Add(4); // Returns new list
Console.WriteLine(numbers.Count); // 3
Console.WriteLine(extended.Count); // 4
// ImmutableDictionary
var users = ImmutableDictionary<int, string>.Empty
```text
.Add(1, "Alice")
.Add(2, "Bob");
var updated = users.SetItem(1, "Alice Smith");
## Pure Functions
### Definition and Benefits
**Pure function characteristics:**
1. Same input always produces same output
2. No side effects (doesn't modify external state)
3. Doesn't depend on external state
**Impure vs Pure:**
```javascript
// ❌ Impure: Depends on external state
let taxRate = 0.08;
function calculateTotalImpure(price) {
```text
return price * (1 + taxRate); // Depends on global variable```
}
// ✅ Pure: All inputs as parameters
function calculateTotal(price, taxRate) {
```text
return price * (1 + taxRate);```
}
// ❌ Impure: Has side effect
let log = [];
function addAndLogImpure(a, b) {
```javascript
const result = a + b;
log.push(result); // Side effect: modifies external array
return result;```
}
// ✅ Pure: Returns both result and new log
function addAndLog(a, b, log) {
```javascript
const result = a + b;
return {
result,
log: [...log, result] // Returns new log, doesn't mutate
};```
}
Pure Functions Across Languages
Python:
## ❌ Impure: Modifies input
def add_item_impure(items: list, item: str) -> list:
```text
items.append(item) # Mutates input
return items
✅ Pure: Returns new list
def add_item(items: list, item: str) -> list:
return [*items, item]
Pure function for data transformation
Figure: Azure Functions monitor – invocation graph, execution timeline, and bindings.
def apply_discount(price: float, discount: float) -> float:
"""Calculate discounted price.
Pure function: No side effects, predictable output.
"""
if discount < 0 or discount > 1:
raise ValueError("Discount must be between 0 and 1")
return price * (1 - discount)
Testable and cacheable due to purity
from functools import lru_cache
@lru_cache(maxsize=128) def fibonacci(n: int) -> int:
"""Pure recursive function with memoization."""
if n < 2:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
**C#:**
```csharp
// Pure function with LINQ
public static IEnumerable<int> FilterEvens(IEnumerable<int> numbers)
{
```javascript
return numbers.Where(n => n % 2 == 0);```
}
// Pure function for validation
public record ValidationResult(bool IsValid, string[] Errors);
public static ValidationResult ValidateEmail(string email)
{
```text
var errors = new List<string>();
if (string.IsNullOrWhiteSpace(email))
errors.Add("Email is required");
if (!email.Contains("@"))
errors.Add("Email must contain @");
return new ValidationResult(errors.Count == 0, errors.ToArray());```
}
// Usage
var result = ValidateEmail("alice@contoso.com");
if (!result.IsValid)
{
```text
Console.WriteLine(string.Join(", ", result.Errors));```
}
Higher-Order Functions
Functions as First-Class Citizens
Functions as arguments:
// JavaScript: Array methods are higher-order functions
const numbers = [1, 2, 3, 4, 5];
// map takes function as argument
const doubled = numbers.map(n => n * 2); // [2, 4, 6, 8, 10]
// filter takes function as argument
const evens = numbers.filter(n => n % 2 === 0); // [2, 4]
// reduce takes function as argument
const sum = numbers.reduce((acc, n) => acc + n, 0); // 15
// Custom higher-order function
function repeat(n, action) {
```javascript
for (let i = 0; i < n; i++) {
action(i);
}```
}
repeat(3, i => console.log(`Iteration ${i}`));
// Output:
// Iteration 0
// Iteration 1
// Iteration 2
Functions returning functions:
## Python: Function factory
def create_multiplier(factor):
```python
"""Returns function that multiplies by factor."""
def multiply(x):
return x * factor
return multiply
double = create_multiplier(2) triple = create_multiplier(3)
print(double(5)) # 10 print(triple(5)) # 15
Decorator as higher-order function
from functools import wraps import time
def timing_decorator(func):
"""Measure function execution time."""
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.2f}s")
return result
return wrapper
@timing_decorator def slow_function():
time.sleep(1)
return "Done"
slow_function() # Prints: slow_function took 1.00s
**C# delegates and lambdas:**
```csharp
// Higher-order function taking delegate
public static List<T> Filter<T>(List<T> items, Func<T, bool> predicate)
{
```text
var result = new List<T>();
foreach (var item in items)
{
if (predicate(item))
result.Add(item);
}
return result;```
}
var numbers = new List<int> { 1, 2, 3, 4, 5 };
var evens = Filter(numbers, n => n % 2 == 0); // [2, 4]
// Function returning function
public static Func<int, int> CreateAdder(int x)
{
```javascript
return y => x + y;```
}
var add5 = CreateAdder(5);
Console.WriteLine(add5(3)); // 8
Console.WriteLine(add5(10)); // 15
Function Composition
Composing Functions
JavaScript/TypeScript:
// Compose functions right-to-left
const compose = <T>(...fns: Array<(arg: T) => T>) => (x: T): T =>
```javascript
fns.reduceRight((acc, fn) => fn(acc), x);
// Pipe functions left-to-right
const pipe =
fns.reduce((acc, fn) => fn(acc), x);
// Example: String processing pipeline const trim = (str: string) => str.trim(); const toLowerCase = (str: string) => str.toLowerCase(); const removeSpaces = (str: string) => str.replace(/\s+/g, "-");
const slugify = pipe(trim, toLowerCase, removeSpaces);
console.log(slugify(" Hello World ")); // "hello-world"
// Compose for data transformation interface User {
name: string;
age: number;```
}
const incrementAge = (user: User): User =>
```text
({ ...user, age: user.age + 1 });
const uppercase Name = (user: User): User =>
({ ...user, name: user.name.toUpperCase() });
const transformUser = compose(uppercaseName, incrementAge);
const user = { name: "alice", age: 30 }; console.log(transformUser(user)); // { name: "ALICE", age: 31 }
**Python with functools:**
```python
from functools import reduce
from typing import Callable, TypeVar
T = TypeVar('T')
def compose(*fns: Callable[[T], T]) -> Callable[[T], T]:
```python
"""Compose functions right-to-left."""
def composed(x: T) -> T:
return reduce(lambda acc, fn: fn(acc), reversed(fns), x)
return composed
def pipe(*fns: Callable[[T], T]) -> Callable[[T], T]:
"""Compose functions left-to-right."""
def piped(x: T) -> T:
return reduce(lambda acc, fn: fn(acc), fns, x)
return piped
Example: Data processing pipeline
def remove_duplicates(items: list) -> list:
return list(dict.fromkeys(items))
def sort_items(items: list) -> list:
return sorted(items)
def take_first_three(items: list) -> list:
return items[:3]
process = pipe(remove_duplicates, sort_items, take_first_three)
data = [3, 1, 4, 1, 5, 9, 2, 6, 5] print(process(data)) # [1, 2, 3]
## Map, Filter, Reduce
### Universal Patterns
**JavaScript:**
```javascript
const products = [
```json
{ name: "Laptop", price: 999, category: "Electronics" },
{ name: "Desk", price: 299, category: "Furniture" },
{ name: "Phone", price: 699, category: "Electronics" },
{ name: "Chair", price: 199, category: "Furniture" }```
];
// map: Transform each element
const prices = products.map(p => p.price);
// [999, 299, 699, 199]
// filter: Keep elements matching condition
const electronics = products.filter(p => p.category === "Electronics");
// [{ name: "Laptop", ... }, { name: "Phone", ... }]
// reduce: Aggregate to single value
const total = products.reduce((sum, p) => sum + p.price, 0);
// 2196
// Chaining operations
const expensiveElectronicsTotal = products
```javascript
.filter(p => p.category === "Electronics")
.filter(p => p.price > 700)
.map(p => p.price)
.reduce((sum, price) => sum + price, 0);```
// 1698 (999 + 699)
Python:
products = [
```json
{"name": "Laptop", "price": 999, "category": "Electronics"},
{"name": "Desk", "price": 299, "category": "Furniture"},
{"name": "Phone", "price": 699, "category": "Electronics"},
{"name": "Chair", "price": 199, "category": "Furniture"}```
]
## map: Transform each element
prices = list(map(lambda p: p["price"], products))
## [999, 299, 699, 199]
![[999, 299, 699, 199]](/images/articles/programming-languages/2025-04-07-functional-programming-concepts-across-languages-sec23-generic.jpg)
## filter: Keep elements matching condition
electronics = list(filter(lambda p: p["category"] == "Electronics", products))
## reduce: Aggregate
from functools import reduce
total = reduce(lambda sum, p: sum + p["price"], products, 0)
## 2196
## List comprehensions (Pythonic alternative)
prices = [p["price"] for p in products]
electronics = [p for p in products if p["category"] == "Electronics"]
total = sum(p["price"] for p in products)
C# LINQ:
var products = new List<Product>
{
```text
new("Laptop", 999, "Electronics"),
new("Desk", 299, "Furniture"),
new("Phone", 699, "Electronics"),
new("Chair", 199, "Furniture")```
};
// Select = map
var prices = products.Select(p => p.Price).ToList();
// [999, 299, 699, 199]
// Where = filter
var electronics = products.Where(p => p.Category == "Electronics").ToList();
// Aggregate = reduce
var total = products.Aggregate(0, (sum, p) => sum + p.Price);
// 2196
// Method chaining (fluent API)
var expensiveElectronicsTotal = products
```javascript
.Where(p => p.Category == "Electronics")
.Where(p => p.Price > 700)
.Sum(p => p.Price);```
// 1698
record Product(string Name, int Price, string Category);
Recursion
Recursive Problem Solving
Factorial:
// JavaScript: Recursive factorial
function factorial(n) {
```text
if (n <= 1) return 1; // Base case
return n * factorial(n - 1); // Recursive case```
}
console.log(factorial(5)); // 120
// Tail-call optimized version
function factorialTCO(n, acc = 1) {
```text
if (n <= 1) return acc;
return factorialTCO(n - 1, n * acc);```
}
Tree traversal:
## Python: Recursive tree traversal
from dataclasses import dataclass
from typing import Optional
@dataclass
class TreeNode:
```yaml
value: int
left: Optional['TreeNode'] = None
right: Optional['TreeNode'] = None
def sum_tree(node: Optional[TreeNode]) -> int:
"""Calculate sum of all node values."""
if node is None:
return 0
return node.value + sum_tree(node.left) + sum_tree(node.right)
def find_max(node: Optional[TreeNode]) -> int:
"""Find maximum value in tree."""
if node is None:
return float('-inf')
left_max = find_max(node.left)
right_max = find_max(node.right)
return max(node.value, left_max, right_max)
Example tree
Figure: Configuration and management dashboard with status overview.
tree = TreeNode(10,
TreeNode(5, TreeNode(3), TreeNode(7)),
TreeNode(15, TreeNode(12), TreeNode(20))```
)
print(sum_tree(tree)) # 72
print(find_max(tree)) # 20
C# pattern matching:
// Recursive sum with pattern matching
public static int Sum(IEnumerable<int> numbers)
{
```javascript
return numbers switch
{
[] => 0, // Empty list
[var first, .. var rest] => first + Sum(rest), // Head + recursive tail
_ => throw new ArgumentException()
};```
}
// Recursive directory processing
public static long GetDirectorySize(string path)
{
```javascript
var directory = new DirectoryInfo(path);
var filesSize = directory.GetFiles()
.Sum(file => file.Length);
var subdirectoriesSize = directory.GetDirectories()
.Sum(subdir => GetDirectorySize(subdir.FullName));
return filesSize + subdirectoriesSize;```
}
Closures
Lexical Scoping
JavaScript:
function createCounter() {
```javascript
let count = 0; // Private variable
return {
increment() {
count++;
return count;
},
decrement() {
count--;
return count;
},
getCount() {
return count;
}
};```
}
const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.getCount()); // 2
console.log(counter.count); // undefined (private)
// Partial application with closures
function multiply(a) {
```text
return function(b) {
return a * b;
};```
}
const double = multiply(2);
const triple = multiply(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
Python:
def create_accumulator(initial=0):
```python
"""Closure for accumulating values."""
total = initial
def add(value):
nonlocal total # Access outer variable
total += value
return total
return add
acc = create_accumulator(10) print(acc(5)) # 15 print(acc(3)) # 18 print(acc(2)) # 20
Decorator using closure
Figure: Configuration and management dashboard with status overview.
def memoize(func):
"""Cache function results."""
cache = {}
def wrapper(*args):
if args not in cache:
cache[args] = func(*args)
return cache[args]
return wrapper
@memoize def expensive_calculation(n):
print(f"Computing {n}...")
return n ** 2
print(expensive_calculation(5)) # Computes and caches print(expensive_calculation(5)) # Uses cache (no print)
## Monads (Optional/Maybe)
### Handling Nullable Values
**TypeScript Optional:**
```typescript
// Custom Optional monad
class Optional<T> {
```javascript
private constructor(private value: T | null) {}
static of<T>(value: T | null): Optional<T> {
return new Optional(value);
}
static empty<T>(): Optional<T> {
return new Optional<T>(null);
}
map<U>(fn: (value: T) => U): Optional<U> {
return this.value !== null
? Optional.of(fn(this.value))
: Optional.empty();
}
flatMap<U>(fn: (value: T) => Optional<U>): Optional<U> {
return this.value !== null
? fn(this.value)
: Optional.empty();
}
getOrElse(defaultValue: T): T {
return this.value !== null ? this.value : defaultValue;
}
isPresent(): boolean {
return this.value !== null;
}```
}
// Usage
interface User {
```yaml
name: string;
email?: string;```
}
function getUser(id: number): Optional<User> {
```javascript
const users: Record<number, User> = {
1: { name: "Alice", email: "alice@contoso.com" },
2: { name: "Bob" }
};
return Optional.of(users[id] ?? null);```
}
const user = getUser(1)
```javascript
.map(u => u.email)
.map(email => email.toUpperCase())
.getOrElse("NO EMAIL");
console.log(user); // "ALICE@contoso.com"
const noEmail = getUser(2)
.map(u => u.email)
.map(email => email.toUpperCase())
.getOrElse("NO EMAIL");
console.log(noEmail); // "NO EMAIL"
**C# with null-conditional operator:**
```csharp
// Functional null handling
public record Address(string City, string? Zip);
public record User(string Name, Address? Address);
// Chain safely without null checks
string GetUserZip(User? user) =>
```text
user?.Address?.Zip ?? "Unknown";
// LINQ for optional values
IEnumerable
users
.Where(u => u.Address != null)
.Select(u => u.Address!.Zip)
.Where(zip => zip != null)
.Cast<string>();
## Best Practices
1. **Immutability**: Prefer immutable data structures, avoid mutations
2. **Pure Functions**: Write functions without side effects for testability
3. **Composition**: Build complex behavior from small, focused functions
4. **Higher-Order Functions**: Use map/filter/reduce over loops
5. **Recursion**: Use for tree/graph traversal, ensure base case
6. **Closures**: Encapsulate private state, create function factories
## Architecture Decision and Tradeoffs
When designing software development solutions with Programming Languages, consider these key architectural trade-offs:
| Approach | Best For | Tradeoff |
|----------|----------|----------|
| Managed / platform service | Rapid delivery, reduced ops burden | Less customisation, potential vendor lock-in |
| Custom / self-hosted | Full control, advanced tuning | Higher operational overhead and cost |
> **Recommendation:** Start with the managed approach for most workloads and move to custom only when specific requirements demand it.
## Validation and Versioning
- Last validated: April 2026
- Validate examples against your tenant, region, and SKU constraints before production rollout.
- Keep module, CLI, and SDK versions pinned in automation pipelines and review quarterly.
## Security and Governance Considerations
- Apply least-privilege access using RBAC roles and just-in-time elevation for admin tasks.
- Store secrets in managed secret stores and avoid embedding credentials in scripts or source files.
- Enable audit logging, data protection policies, and periodic access reviews for regulated workloads.
## Cost and Performance Notes
- Define budgets and alerts, then monitor usage and cost trends continuously after go-live.
- Baseline performance with synthetic and real-user checks before and after major changes.
- Scale resources with measured thresholds and revisit sizing after usage pattern changes.
## Official Microsoft References
- https://learn.microsoft.com/
- https://learn.microsoft.com/azure/
- https://learn.microsoft.com/power-platform/
- https://learn.microsoft.com/microsoft-365/
## Public Examples from Official Sources
- These examples are sourced from official public Microsoft documentation and sample repositories.
- Documentation examples: https://learn.microsoft.com/training/
- Sample repositories: https://github.com/microsoft
- Prefer adapting these examples to your tenant, subscriptions, and governance requirements before production use.
## Key Takeaways
- Immutability prevents bugs from unexpected state changes
- Pure functions are predictable, testable, and cacheable
- Higher-order functions enable abstraction and reusability
- Function composition builds complex logic from simple pieces
- Map/filter/reduce provide declarative data transformation
- Closures enable data privacy and function factories
## Next Steps
- Explore **Ramda.js** or **fp-ts** for functional JavaScript libraries
- Learn **F#** or **Haskell** for pure functional languages
- Study **Category Theory** for advanced functional concepts
- Master **Async Monads** (Promise/Task) for functional async code
## Additional Resources
- [Functional Programming in JavaScript](https://github.com/getify/Functional-Light-JS)
- [Python Functional Programming HOWTO](https://docs.python.org/3/howto/functional.html)
- [C# Functional Programming](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/)
---
*Think in transformations, not mutations.*
Discussion