Functional programming (FP) คือ paradigm ที่หลีกเลี่ยงการเปลี่ยน state และเขียน pure functions ข้อมูลทั้งหมด Immutable (Haskell) variables เหมือนคณิตศาสตร์: กำหนดค่าแล้วเปลี่ยนไม่ได้
Benefits Of Functional Programming
Immutability = ข้อดีหลัก เพราะ mutable data นำไปสู่ subtle bugs ที่ยากต่อการติดตาม
def all_different_from_first?(arr)
first = arr.shift # mutate array!
arr.all? { |n| n != first }
end
arr = [1,3,5,7,9]
all_different_from_first?(arr) # true
arr # [3,5,7,9] # สูญเสีย element 1 โดยไม่รู้ตัว!
Fixed version (immutable):
def all_different_from_first?(arr)
arr[1..-1].all? { |n| n != arr.first }
end
Functional vs OOP
FP ไม่ได้ตรงข้าม OOP สนิท สามารถทำงานร่วมกันได้ Ruby ออกแบบมาเป็น OOP ไม่ควรไป full FP แต่อย่างไรก็ตาม ใช้ แนวคิดที่ดีจาก FP ใน Ruby ได้
Reduce Mutability As Much As Possible
หยุดใช้ attr_accessor ใช้แค่ attr_reader ระวัง methods ที่ mutate: bang methods (gsub!), delete, update, clear, shift/unshift/pop/push ถ้าต้องใช้ ให้ทำงานบน duplicate object:
str = "abcd" dup = str.dup dup.clear # str => "abcd", dup => "" (original safe)
Partial Application (Currying)
Preload arguments บางส่วน:
def add(a,b); a + b; end add_five = method(:add).curry[5] add_five.call(5) # 10 add_five.call(20) # 25
ใช้กับ blocks/lambdas:
list = (1..10)
greater_than = ->(x,y) { y > x }.curry
list.select(&greater_than.(5)) # [6,7,8,9,10]
divisible_by = ->(x,y) { y % x == 0 }.curry
list.select(&divisible_by.(2)) # [2,4,6,8,10]
Summary
FP เน้น pure functions + immutable data เป็นแค่ mindset ไม่ incompatible กับ OOP