คือผมเขียน ML มาได้สักพัก ชอบใจเพราะว่าเป็นภาษาที่มี static typing ที่แทบไม่ต้องบอก type (มันจะหาให้เอง) ทีนี้มีอีกภาษาหนึ่ง ซึ่งคล้ายกันมาก คือ Haskell สองภาษานี้คล้ายกันมาก (ลองดูโปรแกรมที่ http://www.codenone.com/node/22 ) มีเหมือน ๆ กันหมด ทั้งเป็น Functional มี pattern matching อะไรพวกนี้
พอเห็นที่นี่มีคนใช้หลายคน ก็เลยอยากลองเล่นดูบ้่าง แต่ เอ๊ะ ทำไมมันคล้ายกันจัง... เลยไปลอง ๆ หาว่าอืม มันต่างกันตรงไหน
ประเด็นของความแตกต่างคือเรื่องที่ว่า Haskell เป็นภาษาแบบ Lazy evaluation ซึ่งเรามักจะไม่ค่อยเห็นกันในภาษาปกติ กล่าวคือ ในการเรียก function ของภาษาอื่น ๆ (C, Pascal, Java รวมถึง ML ด้วย) argument ต่าง ๆ ของฟังก์ชันจะถูก evaluate ก่อนที่จะเรียกฟังก์ชัน ลักษณะแบบนี้เรียกว่า eagar evaluation
ตัวอย่างที่เห็นได้ชัดก็คือ สมมติเรามีฟังก์ชัน
toInfinity i = i : toInfinity (i+1)
ซึ่งเป็นฟังก์ชันที่เรียกตัวเองไม่รู้จบ สร้าง list ที่มีสมาชิกเพิ่มจาก i ไปเรื่อย ๆ ฟังก์ชันนี้ ถ้าเป็นภาษาอื่น ๆ ฟังก์ชันนี้คงเอาไปใช้ประโยชน์อะไรไม่ได้ เพราะว่าเรียกปุ๊บ เน่าทันใด
อย่างไรก็ตาม ในภาษาที่เป็น lazy evaluation นั้น argument ของฟังก์ชันที่ถูกส่งไป จะไม่ถูก evaluate จนกว่าจะจำเป็น ยกตัวอย่างเช่นถ้าเรามีฟังก์ชัน first ที่ตัดหัวลิสต์มา (เพิ่งลองเล่น ไม่รู้ haskell มีฟังก์ชันประมาณนี้หรือเปล่า) ที่เขียนได้เป็น
first [] _ = [] first _ 0 = [] first (x:xs) i = x:first xs (i-1)
สังเกตว่าฟังก์ชันนี้จะใช้แค่ i ตัวแรกของลิสต์เท่านั้น ดังนั้นถ้าเราเรียก
first (toInfinity 0) 10 -- ได้ผลลัพธ์เป็น [0,1,2,3,4,5,6,7,8,9] first (toInfinity 100) 5 -- ได้ผลลัพธ์เป็น [100,101,102,103,104]
ลองเขียนแบบนี้ในภาษาอื่น ๆ คงจะ run ไม่ออกเพราะว่ามัวแต่ evaluate toInfinity อยู่
ใน Haskell มันทำ lazy evaluation ให้เป็นปกติเลย ส่วนในภาษาอื่น ๆ เช่น ML เท่าที่ลองกด ๆ ดูเห็นว่ามีวิธีทำได้ รวมถึง ใน Python, และ Ruby ด้วย (ดู ของ ruby และ ของ python)
กระทู้เก่าๆ จะย้ายตามไปในภายหลัง ตอนนี้ปิดการโพสต์กระทู้ไว้ เหลือไว้เฉพาะอ้างอิงเท่านั้น
เห็นบางคนก็ใช้ศัพท์ว่า
call-by-need สำหรับพวก lazy evaluation
และ call-by-value สำหรับพวก eager evaluation
คำถามก็คือ plus 1 2, plus 7 2 หรือ mul 2 4 อันไหน จะถูกเรียกใช้ก่อนกัน
คือถ้าเป็น eager evaluation, plus 1 2 ต้องถูก evaluate ก่อนแน่นอน
(เดาเอานะ มันน่าจะทำ left ก่อนแล้วค่อยไป right)
แต่ haskell ไม่ได้รับประกันลำดับในการ evaluate
เราจึงไม่รู้แน่ว่า plus 1 2 หรือ mul 2 4 อันไหนถูกเรียกใช้ก่อน
ปัญหาก็คือลำดับการ evaluate มีผลอย่างมาก
เวลาที่เราติดต่อกับ IO หรือพวก concurrency
haskell จึงแก้ปัญหาพวกนี้โดยใช้ Monad
สำหรับผม อุปสรรคในการเรียกรู้ haskell ก็คือเจ้า monad นี่แหล่ะ
อ่านมานานแล้ว มันซืมเข้าไปนิดเดียว
(ตอนนี้มีความหวังใหม่แล้ว รออาจารย์มะนาว)
อะจ๊าด.... กดเข้าไปอ่านในวิกิพีเดีย ... หมดแรงเลยครับ
เดี๋ยวเราค่อย ๆ แปะตัวอย่าง ยั่ว ๆ คนอื่น ๆ ไปก่อนดีไหมครับ เผื่อมีคนพลังเยอะมาเรียนแล้วเอามาสอน อิอิ
รอคนบ้าพลังมาสอนเหมือนกัน
พลังเยอะ กับบ้าพลัง นี่คงไม่ค่อยเหมือนกันนะครับ