Functional Programming ฉบับเริ่มต้น
ในช่วงพักหลังมานี้ ผมเริ่มสนใจและทำการศึกษาลักษณะการเขียนโปรแกรมแบบ Functional มากขึ้นเรื่อยๆ และก็ค่อยๆ ตกหลุมรักมัน
ในบทความนี้ผมจะขอกล่าวถึงแนวคิดพื้นฐานของการเขียนโค้ดสไตล์ functional ที่ได้ศึกษามา และตัวอย่างเล็กน้อยให้ได้เห็นภาพกัน
แนวคิดของ Functional Programming
สำหรับ Functional Programming นั้น ข้อมูลของเรา จะถูกเปลี่ยนแปลงได้ ผ่านทางฟังก์ชันเท่านั้น
ตัวอย่าง การหาผลรวมสำหรับค่าตัวแปร balance และ salary
function plus (a, b) {
return a + b
}const balance = 12000
const salary = 15000plus(balance, salary) // 27000
ตัวอย่าง การหาค่า 20% ของตัวแปร balance
function calculateTax (number) {
return number * 0.2
}const balance = 27000calculateTax(balance) // 5400
โดยจากโค้ดตัวอย่างด้านบนนั้น เป็นฟังก์ชันที่เราจะเรียกว่า Pure Function ซึ่งเราจะทำการพูดถึงในส่วนถัดไป
Pure Function คืออะไร?
Pure Function คือฟังก์ชันที่ถูกเขียนขึ้นโดยมีลักษณะการทำงานตามกฎง่ายๆ ดังต่อไปนี้
- ค่าที่ return จะเปลี่ยนแปลงไปตามค่าของ arguments ที่รับเข้ามา
- ไม่เกิด side effects
กล่าวคือ เมื่อฟังก์ชันของเรารับค่าอะไรเข้าไป ไม่ว่าจะที่ไหน หรือเมื่อไหร่ หากรับค่าแบบเดียวกันเข้าไป ผลลัพธ์ที่ได้ต้องเหมือนกัน
ซึ่งนั่นหมายความว่า ค่าของตัวแปรภายนอกต้องไม่ส่งผลต่อการคำนวณ และหลังจากคำนวณต้องไม่ส่งผลต่อตัวแปรภายนอกเช่นเดียวกัน
ตัวอย่าง Pure Function
function plus (a, b) {
return a + b
}const balance = 12000
const salary = 15000plus(balance, salary) // 27000
plus(balance, salary) // 27000
plus(balance, salary) // 27000
ตัวอย่างข้างต้นนี้ ถือเป็น Pure Function เนื่องจากไม่ว่าเราจะเรียกฟังก์ชัน plus ที่ไหน หรือเมื่อไหร่ หากเราใส่ค่า 12,000 และ 15,000 เข้าไป ผลลัพธ์ที่ได้จะออกมาจะมีค่าเท่ากับ 27,000 เสมอ
ตัวอย่าง Impure Function (หรือฟังก์ชันที่ไม่ใช่ Pure Function)
let count = 0function increase () {
return count++
}increase() // 0
increase() // 1
increase() // 2
จากตัวอย่างข้างต้นจะเห็นว่าเมื่อเราเรียกฟังก์ชัน increase ผลลัพธ์ที่ได้จะต่างออกไปเสมอ เนื่องจากมันเกิดสิ่งที่เรียกว่า side effect ขึ้นกับตัวแปร count
ทำไมต้องเขียน Functional?
เราจะทำการลองสร้างฟังก์ชันซึ่งทำการยกกำลังค่าทั้งหมดภายใน arrays ที่รับเข้ามา ด้วยการเขียนแบบปกติ กับการเขียนในแบบ functional
เขียนแบบทั่วไป
function double(numbers) {
const doubleNumbers
for (let i = 0; i < numbers.length; i++) {
doubleNumbers.push(numbers[i] * numbers[i])
}
return doubleNumbers;
}
double([1, 2, 3, 4]) // [1, 4, 9, 16]
จากตัวอย่างด้านบน จะเห็นว่าโค้ดของเรานั้นมีการใช้ loop ซึ่งหมายความว่าโอกาสเกิด bug ในโค้ดของเราจะเพิ่มขึ้นจากจุดนี้นั่นเอง
รวมไปถึงการใช้ loop อาจก่อให้เกิด side effect ขึ้นภายในได้ ซึ่งยากต่อการตรวจสอบ
และที่สำคัญที่สุด….. มันไม่สวยเอาซะเลย!
เขียนแบบ functional
function double(numbers) {
return numbers.map(num => num * num)
}
double([1, 2, 3, 4]) // [1, 4, 9, 16]
เป็นไง? สวยงามขึ้นเยอะเลย
และที่สำคัญโอกาสในการเกิด bug จากการใช้ loop จะลดน้อยลงตามไปด้วย พร้อมทั้งยังไม่เกิด side effect ใดๆ ในโค้ดของเรา
สำหรับบทความหน้า ผมจะเขียนถึงตัวอย่างที่ผมใช้เขียนโค้ดสไตล์ functional ใน JavaScript ด้วย lodash/fp
หากเพื่อนๆ สนใจยังไงก็ อย่าลืมติดตาม หรือแวะมาพูดคุยกันนะครับ XD