(FP) Mutable Function VS Immutable Function

imKrish Developer
imKrish
Published in
2 min readNov 28, 2016

สวัสดีครับ วันนี้ก็มาทำความรู้จักกับ Immutability กันครับ

Immutability ในที่นี้ก็คือการไม่เปลี่ยนแปลงครับ

การกลายพันธุ์ เป็นปรากฎการณ์ที่ไม่มีใครคาดถึง

ในโปรแกรมของเรา ปกติแล้ว เราจะมี State มี Variable เอาไว้เก็บค่าต่างๆ
แล้วใช้ Function เปลี่ยนแปลงค่าเหล่านั้น (Mutable Function)

ซึ่งถามว่ามันดีไหม บอกเลยว่าไม่ดีครับ! แย่มากๆ! ยกตัวอย่างถ้าเพื่อนๆมี Global State ค่านึง แล้วมีหลายส่วนของโปรแกรมเข้าถึงค่าเหล่านั้น วันนึงถ้า Global State ค่านั้นเปลี่ยนไปเป็น undefine, null หรือ เป็น type เป็นค่า ที่เราไม่ได้ต้องการ เนื่องจากมีหลาย Function เข้าถึงค่านี้ มันก็ส่งผลให้โปรแกรมของเราทำงานผิดปกติ!!!

ยิ่งมีหลายส่วนของ Code เข้าถึง Global State มากเท่าไร บอกเลยว่ายิ่งแย่, Maintain ยาก, Test ก็ยาก

วิธีแก้คือ แทนที่จะใช้ Function ที่เปลี่ยนค่า State เหล่านั้น ให้เราสร้าง Function ที่สร้างค่านั้นขึ้นมาใหม่หากมีการเปลี่ยนแปลงครับ และนี้ก็คือที่มาของ Immutable Function

ผมขอยกตัวอย่างใน Javascript นะครับ จาก Function ใน Standard Library เรามี map, filter, reduce, sort(Mutable Function) ไว้จัดการกับ Array

Mutable Function

Mutable Function คือ Function ที่เปลี่ยนแปลงค่า Argument ที่รับเข้ามา หรือค่าที่อยู่ภายนอก Scope ของมัน

Note: ปกติแล้ว Argument ที่รับเข้ามาจะมีแบบ Pass by Value (พวก Primitive Type เช่น string, number) กับ Pass by Reference (พวก Object, Array)

ซึ่งที่เป็นปัญหาก็คือ Pass by Reference นี้แหละครับ

ยกตัวอย่าง Array.sort เป็น Mutable Function

const numbers = [5, 1, 7, 9, 15, 2]// Sort จากค่ามากไปหาน้อย
numbers.sort((num1, num2) => num2 - num1)
> [15, 9, 7, 5, 2, 1]
numbers
> [15, 9, 7, 5, 2, 1]

จากตรงนี้สังเกตได้ว่า Array.sort เนี่ยไม่ใช่แค่ Sort อย่างเดียวนะ มันไปเปลี่ยนแปลงตำแหน่งของ numbers ด้วย

คราวนี้ยกตัวอย่างถ้ามี Part นึงของระบบ
เข้าถึง numbers ที่โดนเปลี่ยนแปลงค่าไปแล้ว

if (numbers[0] === 5) {
done()
} else {
throw new Error("The first element of number must be 5")
}

ที่จะสื่อคือในบางกรณีเราไม่ได้ expect ว่าบางค่าในระบบมันจะเปลี่ยนไป แล้วพอมันเปลี่ยนไป Function อื่นๆที่เข้าถึงค่านี้ มันก็ทำงานผิดปกติไปด้วย เพราะฉะนั้นเลี่ยง Mutable Function ได้เราควรเลี่ยง แล้วก็ใช้ Global State ให้น้อยที่สุดด้วย

Immutable Function

ก็คือ Function ที่ไม่เปลี่ยนแปลงค่า Argument ที่รับเข้ามา แล้วก็ไม่เปลี่ยนแปลงค่าใดๆที่อยู่ใน Outer Scope นั่นเอง

อ่านมาถึงตรงนี้แล้วเพื่อนๆ คงคิดได้ว่า Immutable Functon มันก็คือ Pure Function นี้เอง นั่นแหละครับใช่เลย

ถ้า Function ที่คุณสร้างขึ้นมัน Pure มันก็จะเป็น Immutable Function ไปโดยปริยาย

const cloneArray = arr => JSON.parse(JSON.stringify(arr))const sortDesc = (num1, num2) => num2 - num1const immutableSort = arr => cloneArray(arr).sort(sortDesc)

ก็ง่ายๆครับ ถ้าเป็น Pass by Reference แล้วเรารู้ว่าจะมีการเปลี่ยนแปลงค่ามัน เราก็ทำการ Clone มันก่อน อันนี้ผมใช้วิธีง่ายๆนะครับคือเปลี่ยนมันให้เป็น JSON String ก่อน แล้วก็ Convert มันกลับมาให้เป็น Array ใหม่ เพียงเท่านี้เราก็ได้ Sort ที่เป็น Immutable Function แล้ว

สุดท้ายนี้ถ้าเราไม่อยากมานั่ง Implement Immutable Function หรือ Pure Function เอง แนะนำให้ใช้ Library นะครับ ที่นิยมกันตอนนี้ก็มี LodashJS กับ RamdaJS ครับผม

ตัวอย่างการใช้ LodashJS ฮะ

const enrollment = [
{enrolled: 2, grade: 100},
{enrolled: 2, grade: 80},
{enrolled: 1, grade: 89}
]
_(enrollment)
.filter(student => student.enrolled > 1)
.map("grade")
.mean()
> 90
// filter, map, mean เป็น Immutable Function(Pure Function) ทั้งหมด

เดี๋ยวยังไงถ้าว่างๆผมอาจจะมาสอนการใช้ LodashJS เบื้องต้นนะครับผมม

ขอบคุณที่อ่านจนจบนะครับ

อ่านแล้ว ยังไงก็ช่วยกดหัวใจเป็นกำลังใจให้หน่อยนะครับ

แล้วก็ฝากแฟนเพจด้วยจ้า : )

https://www.facebook.com/imkrish.developer/

“ Happiness is Only Real When Shared ”

ที่เริ่มเขียน Blog เพราะไปเจอ Quote นี้นี้แหละครับ :)

--

--

imKrish Developer
imKrish

I’m going to be the best I could be, not someone tells me I should be. I am optimistic and I love freedom : )