-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathfunctional_programming.ts
More file actions
147 lines (120 loc) · 3.92 KB
/
functional_programming.ts
File metadata and controls
147 lines (120 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/**
* Functional Programming Concepts
*
* Functional programming emphasizes immutability, pure functions,
* and higher-order functions. These concepts lead to more predictable
* and maintainable code.
*
* Key Concepts:
* - Pure functions
* - Immutability
* - Higher-order functions
* - Map, Filter, Reduce
* - Function composition
* - Currying
*/
// Pure Functions (no side effects, same input = same output)
function add(a: number, b: number): number {
return a + b; // Pure: no side effects
}
// Impure function (has side effect)
let counter = 0;
function impureIncrement(): number {
counter++; // Side effect: modifies external state
return counter;
}
// Immutability - Don't mutate, create new objects
interface User {
name: string;
age: number;
}
// Bad: Mutating
function updateAgeBad(user: User, newAge: number): void {
user.age = newAge; // Mutates original
}
// Good: Immutable
function updateAgeGood(user: User, newAge: number): User {
return { ...user, age: newAge }; // Returns new object
}
// Map - Transform each element
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2); // [2, 4, 6, 8, 10]
const strings = numbers.map(n => n.toString()); // ["1", "2", "3", "4", "5"]
// Filter - Select elements that match condition
const evens = numbers.filter(n => n % 2 === 0); // [2, 4]
const odds = numbers.filter(n => n % 2 !== 0); // [1, 3, 5]
// Reduce - Accumulate values
const sum = numbers.reduce((acc, n) => acc + n, 0); // 15
const product = numbers.reduce((acc, n) => acc * n, 1); // 120
const max = numbers.reduce((acc, n) => n > acc ? n : acc, numbers[0]); // 5
// Chaining
const result = numbers
.filter(n => n % 2 === 0) // [2, 4]
.map(n => n * 2) // [4, 8]
.reduce((acc, n) => acc + n, 0); // 12
// Higher-Order Functions (functions that take/return functions)
function multiplyBy(factor: number): (n: number) => number {
return (n: number) => n * factor;
}
const double = multiplyBy(2);
const triple = multiplyBy(3);
// Function Composition
type Func<T, R> = (arg: T) => R;
function compose<T, U, V>(f: Func<U, V>, g: Func<T, U>): Func<T, V> {
return (x: T) => f(g(x));
}
const addOne = (x: number) => x + 1;
const multiplyByTwo = (x: number) => x * 2;
const addOneThenDouble = compose(multiplyByTwo, addOne);
// addOneThenDouble(5) = multiplyByTwo(addOne(5)) = multiplyByTwo(6) = 12
// Currying (transforming multi-argument function into single-argument functions)
function addCurried(a: number): (b: number) => number {
return (b: number) => a + b;
}
const add5 = addCurried(5);
const result1 = add5(3); // 8
// More practical currying example
function createLogger(prefix: string): (message: string) => void {
return (message: string) => {
console.log(`[${prefix}] ${message}`);
};
}
const errorLogger = createLogger("ERROR");
const infoLogger = createLogger("INFO");
// Partial Application
function multiply(a: number, b: number, c: number): number {
return a * b * c;
}
function partialMultiply(a: number): (b: number) => (c: number) => number {
return (b: number) => (c: number) => multiply(a, b, c);
}
const multiplyBy2And3 = partialMultiply(2)(3);
const result2 = multiplyBy2And3(4); // 24
// Memoization (caching function results)
function memoize<T extends (...args: any[]) => any>(fn: T): T {
const cache = new Map<string, ReturnType<T>>();
return ((...args: Parameters<T>) => {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = fn(...args);
cache.set(key, result);
return result;
}) as T;
}
const expensiveFunction = (n: number): number => {
// Simulate expensive computation
return n * n;
};
const memoizedExpensive = memoize(expensiveFunction);
export {
add,
updateAgeGood,
multiplyBy,
compose,
addCurried,
createLogger,
partialMultiply,
memoize
};