Dark mode
Functional Programming
แนวคิดหลัก
Pure Functions: ฟังก์ชันที่ไม่มีผลข้างเคียง (side effects) และให้ผลลัพธ์เดียวกันเสมอเมื่อรับอินพุตเดียวกัน
javascript
// Pure function
function add(a, b) {
return a + b;
}
// Impure function (has side effect)
let total = 0;
function addToTotal(value) {
total += value; // modifies external state
return total;
}
rust
// Pure function
fn add(a: i32, b: i32) -> i32 {
a + b
}
// Impure function (has side effect)
static mut TOTAL: i32 = 0;
fn add_to_total(value: i32) -> i32 {
unsafe {
TOTAL += value; // modifies external state
TOTAL
}
}
python
# Pure function
def add(a, b):
return a + b
# Impure function (has side effect)
total = 0
def add_to_total(value):
global total
total += value # modifies external state
return total
go
package main
// Pure function
func add(a, b int) int {
return a + b
}
// Impure function (has side effect)
var total = 0
func addToTotal(value int) int {
total += value // modifies external state
return total
}
Immutability: ข้อมูลไม่สามารถเปลี่ยนแปลงได้หลังจากสร้างขึ้น ต้องสร้างข้อมูลใหม่แทนการแก้ไข
javascript
// Immutable approach
const originalArray = [1, 2, 3];
const newArray = [...originalArray, 4]; // creates new array
// Mutable approach (avoid in functional programming)
const array = [1, 2, 3];
array.push(4); // modifies original array
rust
// Immutable approach
fn main() {
let original_vec = vec![1, 2, 3];
let new_vec = [&original_vec[..], &[4]].concat(); // creates new vector
// Mutable approach (avoid in functional programming)
let mut vec = vec![1, 2, 3];
vec.push(4); // modifies original vector
}
python
# Immutable approach
original_list = [1, 2, 3]
new_list = original_list + [4] # creates new list
# Mutable approach (avoid in functional programming)
my_list = [1, 2, 3]
my_list.append(4) # modifies original list
go
package main
// Immutable approach
func main() {
originalSlice := []int{1, 2, 3}
newSlice := append([]int{}, originalSlice...) // copy slice
newSlice = append(newSlice, 4) // append to copy
// Mutable approach (avoid in functional programming)
slice := []int{1, 2, 3}
slice = append(slice, 4) // modifies original if capacity allows
}
Higher-Order Functions: ฟังก์ชันที่รับฟังก์ชันเป็นอาร์กิวเมนต์หรือคืนค่าเป็นฟังก์ชัน
javascript
// Function that takes a function as argument
const map = (array, fn) => array.map(fn);
const double = x => x * 2;
console.log(map([1, 2, 3], double)); // [2, 4, 6]
// Function that returns a function
const multiply = x => y => x * y;
const triple = multiply(3);
console.log(triple(4)); // 12
rust
// Function that takes a function as argument
fn map<F>(array: &[i32], f: F) -> Vec<i32>
where F: Fn(i32) -> i32
{
array.iter().map(|&x| f(x)).collect()
}
fn main() {
let double = |x| x * 2;
println!("{:?}", map(&[1, 2, 3], double)); // [2, 4, 6]
// Function that returns a function
fn multiply(x: i32) -> impl Fn(i32) -> i32 {
move |y| x * y
}
let triple = multiply(3);
println!("{}", triple(4)); // 12
}
python
# Function that takes a function as argument
def map_values(array, fn):
return [fn(x) for x in array]
double = lambda x: x * 2
print(map_values([1, 2, 3], double)) # [2, 4, 6]
# Function that returns a function
def multiply(x):
def inner(y):
return x * y
return inner
triple = multiply(3)
print(triple(4)) # 12
go
package main
import "fmt"
// Function that takes a function as argument
func mapValues(array []int, fn func(int) int) []int {
result := make([]int, len(array))
for i, v := range array {
result[i] = fn(v)
}
return result
}
func main() {
double := func(x int) int { return x * 2 }
fmt.Println(mapValues([]int{1, 2, 3}, double)) // [2, 4, 6]
// Function that returns a function
multiply := func(x int) func(int) int {
return func(y int) int {
return x * y
}
}
triple := multiply(3)
fmt.Println(triple(4)) // 12
}
Function Composition: การรวมฟังก์ชันหลายตัวเข้าด้วยกันเพื่อสร้างฟังก์ชันใหม่
javascript
// Simple composition
const compose = (f, g) => x => f(g(x));
const addOne = x => x + 1;
const double = x => x * 2;
const doubleAndAddOne = compose(addOne, double);
console.log(doubleAndAddOne(3)); // 3 * 2 + 1 = 7
rust
// Simple composition
fn compose<F, G, T>(f: F, g: G) -> impl Fn(T) -> T
where
F: Fn(T) -> T,
G: Fn(T) -> T,
T: Copy,
{
move |x| f(g(x))
}
fn main() {
let add_one = |x| x + 1;
let double = |x| x * 2;
let double_and_add_one = compose(add_one, double);
println!("{}", double_and_add_one(3)); // 3 * 2 + 1 = 7
}
python
# Simple composition
def compose(f, g):
return lambda x: f(g(x))
add_one = lambda x: x + 1
double = lambda x: x * 2
double_and_add_one = compose(add_one, double)
print(double_and_add_one(3)) # 3 * 2 + 1 = 7
go
package main
import "fmt"
// Simple composition
func compose(f func(int) int, g func(int) int) func(int) int {
return func(x int) int {
return f(g(x))
}
}
func main() {
addOne := func(x int) int { return x + 1 }
double := func(x int) int { return x * 2 }
doubleAndAddOne := compose(addOne, double)
fmt.Println(doubleAndAddOne(3)) // 3 * 2 + 1 = 7
}
Recursion: การเรียกฟังก์ชันตัวเองซ้ำๆ แทนการใช้ลูป
javascript
// Recursive factorial function
function factorial(n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
console.log(factorial(5)); // 120
// Instead of imperative loop:
// function factorial(n) {
// let result = 1;
// for (let i = 2; i <= n; i++) {
// result *= i;
// }
// return result;
// }
rust
// Recursive factorial function
fn factorial(n: u64) -> u64 {
if n <= 1 {
return 1;
}
n * factorial(n - 1)
}
fn main() {
println!("{}", factorial(5)); // 120
// Instead of imperative loop:
// fn factorial(n: u64) -> u64 {
// let mut result = 1;
// for i in 2..=n {
// result *= i;
// }
// result
// }
}
python
# Recursive factorial function
def factorial(n):
if n <= 1:
return 1
return n * factorial(n - 1)
print(factorial(5)) # 120
# Instead of imperative loop:
# def factorial(n):
# result = 1
# for i in range(2, n + 1):
# result *= i
# return result
go
package main
import "fmt"
// Recursive factorial function
func factorial(n uint64) uint64 {
if n <= 1 {
return 1
}
return n * factorial(n-1)
}
func main() {
fmt.Println(factorial(5)) // 120
// Instead of imperative loop:
// func factorial(n uint64) uint64 {
// result := uint64(1)
// for i := uint64(2); i <= n; i++ {
// result *= i
// }
// return result
// }
}
เหมาะสำหรับ
- การประมวลผลข้อมูลแบบขนาน (Parallel Processing)
- การจัดการกับโครงสร้างข้อมูลขนาดใหญ่
- ระบบที่ต้องการความน่าเชื่อถือและทดสอบง่าย
- การพัฒนาซอฟต์แวร์ที่ซับซ้อนและต้องการบำรุงรักษาในระยะยาว
- ระบบที่ต้องการความปลอดภัยสูงและลดข้อผิดพลาด