ช่วงนี้ได้อ่านหนังสือ “The Ruby Programming Language” ทำให้มีโอกาสได้รู้เทคนิค หรือฟีเจอร์ของภาษา Ruby หลายอย่าง แม้ว่าจะใช้ Ruby มาตั้งแต่สมัยอยู่ญี่ปุ่น แต่ยังไม่เคยมีโอกาสอ่านหนังสือจริงๆ จังๆ ส่วนใหญ่ก็ใช้ไปแบบงูๆ ปลาๆ เหตุผลเดียวที่ใช้ก็คือรู้สึกว่า syntax ค่อนข้างคงที่ไม่กำกวม แถมยังเป็น OOP ทำให้ง่ายต่อการทำงานบางอย่าง วันนี้เพิ่งอ่านเจอว่าเราสามารถเขียน method ที่รับอาร์กิวเมนต์จำนวนไม่คงที่ได้ โดยใช้วิธีการกำหนดพารามิเตอร์เพิ่มหนึ่งตัว นอกเหนือจากพารามิเตอร์ปกติ และให้ใส่เครื่องหมาย * ไว้ข้างหน้าพารามิเตอร์ตัวนั้น เช่น
def min(first, *rest) min=first rest.each {|x| min=x if x<min} return min end
method นี้จะหาค่าต่ำที่สุดของอาร์กิวเมนต์ทั้งหมดที่รับมา เช่น
>> min(4,2,1,5) => 1
โดย first เป็นพารามิเตอร์หลัก หมายความว่าจะต้องรับข้อมูลมาอย่างน้อยหนึ่งตัว ส่วน rest เป็นพารามิเตอร์สำหรับค่าอื่นๆ ที่เหลือ ในที่นี้เมื่ออ้างถึง rest จะเป็นอะเรย์เก็บค่าต่างๆ ที่ได้รับมา ดังนั้นจึงสามารถใช้ rest.each ในการอ้างถึงสมาชิกแต่ละตัว แล้วเปรียบเทียบหาค่าต่ำที่สุดได้
ลองดูฟีเจอร์นี้ของ Ruby แล้ว ก็รู้สึกว่าไม่ต่างจากรูปแบบลิสต์ [head|tail] ของ Prolog คือลิสต์ถูกแบ่งเป็นสองส่วน ได้แก่ ส่วนหัว กับส่วนที่เหลือ (ตรงนี้จะต่างจากภาษา C ที่ใช้วิธีกำหนดทั้งหมดไว้ในอะเรย์ แล้วระบุจำนวนอาร์กิวเมนต์มาให้) เลยอยากจะลองเขียน method reverse สำหรับสลับลำดับข้อมูลในลิสต์เรียงกลับจากลำดับเดิม โดยใช้วิธี recursive แบบ Prolog ดู
reverse([],[]). reverse([H|T], R) :- reverse(T,TR), append(T,[H],R).
def reverse(first, *rest) if rest.empty? return [first] else return reverse(*rest) << first end end
ลองเทียบกันดูในแง่ความหมาย จะเห็นว่่าเหมือนกันเป๊ะๆ แถมยังใช้เครื่องหมายคล้ายๆ กันอีก จุดที่แตกต่างที่สุดก็เห็นจะอยู่ที่ลักษณะของ reverse ใน Ruby เป็นฟังก์ชันมีการส่งค่ากลับ ส่วน reverse ของ Prolog เป็น predicate แสดงความสัมพันธ์ระหว่าง list สองอัน
เป็นอันสิ้นสุดการทดลองของวันนี้แต่เพียงเท่านี้
Tags: programming, prolog, ruby