วงแหวนเว็บ

neizod's speculation

insufficient data for meaningful answer

Function Composition กับ Programming

Friday, August 17, 2012, 03:42 PM

ตอนม.ปลาย คงเคยเห็นฟังก์ชั่นที่เขียนแทนด้วยสัญลักษณ์ $g \circ f$ กันมาแล้ว ซึ่งมันหมายความง่ายๆ เช่นนี้

\[(g \circ f) (x) = g(f(x))\]

(นิยามเต็มๆ ของมันคือ ถ้า $f: X \to Y$ และ $g: Y \to Z$ แล้ว $g \circ f: X \to Z$ – ที่ต้องนิยามเช่นนี้เพราะเราจะสามารถละการเขียนตัวแปร $x$ ติดไปกับนิยามได้)

ในการเขียนโปรแกรม (โดยเฉพาะเชิง functional) เรามักต้องทำงานแบบฟังก์ชันต่อเนื่อง คือ output จาก function หนึ่ง จะถูกนำมาใช้เป็น input ให้ฟังก์ชันถัดไปเป็นลูกโซ่

เขียนอธิบายเป็นภาษาโปรแกรมได้คือ

first_input = x
first_output = f(first_input)
second_input = first_output
second_output = g(second_input)
y = second_output

หรือเพื่อไม่ให้เปลืองตัวแปร ทั้งหมดนี้สามารถย่อได้เหลือ

y = g(f(x))

คำถามคือ ถ้าเราต้องการประกาศแค่ฟังก์ชั่นที่ทำงานต่อกันไปเรื่อยๆ เช่นนี้ โดยที่ไม่ต้องการใส่ input ให้ฟังก์ชั่นโดยทันที เราจะทำอย่างไร?

ทางออกหนึ่งคือใช้ lambda เข้าช่วย

h = lambda x: g(f(x))

แล้วเวลาจะเรียกใช้ฟังก์ชั่นนี้ ก็แค่สั่ง

y = h(x)

ฟังดูง่ายดี แต่นึกดูอีกที ทำไมเราถึงต้องทำอะไรให้มันยุ่งยากด้วยการเอา lambda เข้ามาเกี่ยวด้วย?

ในภาษา imperative คงไม่มีทางเลือกอื่น แต่สำหรับภาษา functional จ๋าอย่าง Haskell เราสามารถเขียนแบบนี้ได้

let h = g . f

จะเห็นว่าง่ายดายเหมือนกับ $g \circ f$ ตอนแรกเลย เวลาใช้ก็แค่

h x

หรือถ้าจะละการประกาศฟังก์ชั่น $h$ ทิ้งไป เพื่อหาผลลัพท์ทันทีเลย ก็ทำได้โดย

(g . f) x

อ่าห์… นี่มันคณิตศาสตร์ชัดๆ!!

neizod

author