Photo by Priscilla Du Preez on Unsplash

ประโยชน์ของ Higher Order Function

Peerawat Poombua
odds.team
Published in
2 min readDec 3, 2019

--

หลายๆ คนที่เขียน Javascript มาถึงจุดนึงจะพบกับสิ่งที่เรียกว่า Higher Order Function หรือ เรียกสั้นๆ ว่า HOF มันคือการที่ Function สามารถรับ Input เป็น Function และ/หรือ Return Output เป็น Function ได้

แล้วไงวะ? มีประโยชน์กับชีวิตกูยังไงนะ? (ผมได้ยินเสียงจากทางบ้าน)

ซึ่งผมกำลังจะพยายามอธิบายนี่แหละครับ โดยที่ขอกลับมาที่พื้นฐานของ Function กันก่อน

Function คือ สิ่งที่ Map Input ไป Output

ซึ่งปกติเราจะคิดว่า Input ก็คือ Value จาก Type นึง และ Output ก็เป็น Value ที่อาจจะมี Type เดียวกับ Input หรือต่าง Type กัน

เช่น

function Square(n) { return n * n } // รับ input เป็น number และ return output เป็น number

และ

function isOdd(n) { return n % 2 === 1 } // รับ input เป็น number และ return output เป็น boolean

แต่ทีนี้ถ้าผมบอกว่า ผมมีงานสองอย่างซึ่งผมรู้ว่าทั้ง 2 งานนี้มันรับ Input แบบเดียวกันเลย ผมอยากจะ Apply งานสองงานนี้กับ Input ชุดเดียวกัน ผมจะทำยังไงดีนะ

ถ้าเป็น Imperative Style เราก็จะวน Loop กันไป มี Loop สอง Loop ทำคนละงาน จบ!

หรือ ผมอาจจะคิดในอีกแบบนึง ผมคิดว่า ถ้าผมมี Function ซักอันที่มันจะคอย Map ระหว่าง “Input” ของผม กับ “งาน” ที่ผมจะทำกับมัน มันก็น่าจะดูดีนะ เช่น

function map(inputs, งาน) { …map งาน with each input… }

ซึ่งใน Javascript มันก็มี Function ชื่อนี้อยู่แล้วใน Array.prototype ผมขอเอามาใช้เลยละกัน ดังนั้นผลที่ได้ก็จะออกมาหน้าตาแบบนี้ครับ

[1,2,3,4].map(Square) // [1, 4, 9, 16][1,2,3,4].map(isOdd) // [true, false, true, false]

หล่อปะหละ

ต่อมา กลับมาที่ Function isOdd เมื่อตอนต้น ผมบอกว่า ผมอยากได้ Function isEven ผมทำยังไงดี

แน่นอน ผมเชื่อว่า สมองของ Programmer ทุกคนทำงานที่ระดับความเร็วแสง ในเพียงเสี้ยววินาทีเราจะได้ Function หน้าตาแบบนี้

function isEven(n) { return n % 2 === 0 }

ซึ่งมันก็ทำงานถูก ดูดีฮะ ไม่ผิดอะไรด้วย

แต่ผมขออนุญาตพาทุกคนไปอีกทางนึง ผมบอกว่า function isEven ของผม หน้าตาแบบนี้นะ

function isEven(n) { return !isOdd(n) }

แล้วมันต่างจากเดิมยังไงวะ? (ผมได้ยินเสียงจากทางบ้านอีกแล้ว)

ซึ่งขอตอบว่า ถ้าจะเอาแค่ผล มันไม่ต่างกันครับ แต่แบบที่ผมเสนอ มันบ่งบอก Relation ระหว่าง isEven กับ isOdd ว่า งานสองงานนี้ จริงๆ แล้วมันเป็น “นิเสธ” (ตรงข้าม) กัน

(บางคนอาจจะมองว่า Reuse ก็ได้ แต่ตรงนั้นไม่ใช่ประเด็นสำคัญครับ)

มาถึงตรงนี้ ผมคิดว่ามันน่าจะดีนะ ถ้าเรามี Function อันนึง ที่บอกถึงความสัมพันธ์ตรงนี้ได้ ซึ่งแน่นอนว่า มันก็จะคล้ายๆ กับ Function map นั่นแหละ แต่มันจะรับ Input เป็น Function และ return Output เป็น Function ที่ทำงานเป็น “นิเสธ” กับ Function ที่รับเข้ามา

ซึ่งหน้าตามันก็น่าจะประมาณนี้ครับ

function not(fn) {
return function negated(..args) {
return !fn(…args)
}
}

แล้วเราก็จะทำแบบนี้ได้ครับ

const isEven = not(isOdd)isEven(4) // true

ก่อนจบ อยากจะกลับมาเรื่อง Type นิดนึง

คือ เมื่อก่อนเราจะคิดถึง Type แค่เป็น กล่องเก็บของ size ต่างๆ กัน แต่การมาของ Javascript ที่มันมอง Function ว่าเป็น Type อันนึงเนี่ย มันทำให้เราปวดแก่นกะโหลกพอสมควร เพราะในหัวเรายังคิดถึงกล่องอยู่เลย แล้ว Function มันเป็นกล่องได้ไงวะ ถึงจุดนี้แหละที่เราต้องเปลี่ยนความคิดแล้วว่า Type ไม่ใช่กล่อง แต่ Type คือ นิยาม ต่างหาก (ง่ายสุดให้คิดถึง Set)

ดังนั้น HOF ทำให้เราสามารถใช้ประโยชน์ของ Function ในการ Map จาก Type ไปสู่ Type ได้อย่างแท้จริงครับ

ขอต้อนรับเข้าสู่ Functional Programming ครับ

ผิดพลาดประการใดบอกได้เลยนะครับ ผมอาจจะเมายา 😂

--

--

Peerawat Poombua
odds.team

Developer who seek for understanding. Mainly use Javascript and Golang. Passionate for software craftsmanship. Try to be useful at ODDS