msgbartop
Just another blog of mine
msgbarbottom

10 Apr 08 Ruby กับ Prolog

ช่วงนี้ได้อ่านหนังสือ “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: , ,

10 Apr 08 Ruby กับ UTF8

คิดว่าคงจะรู้กันโดยทั่วไปแล้ว ว่าเราสามารถใช้ Ruby กับ String ที่เข้ารหัสแบบ UTF-8 ได้ ที่ว่าใช้ได้นี่หมายความว่า ได้ข้อมูล (ข้อความ) มา ก็สามารถเก็บลงไปในตัวแปรได้เลย ไม่เกิดปัญหาอะไร แต่โดยการทำงานจริงๆ แล้ว Ruby ไม่ได้สนับสนุน UTF-8 หรือการเข้ารหัสข้อความแบบใดๆ ทั้งสิ้น เพียงแค่พิจารณาว่า String ก็คือลำดับของตัวอักษร ที่ตัวอักษรหนึ่งตัวมีขนาดเท่ากัน (จะเป็น 1 ไบต์ หรือ 2 ไบต์ ก็แล้วแต่การใช้งาน) ดังนั้นจึงใช้กับ UTF-8 ที่เก็บตัวอักษรแต่ละตัวด้วยที่ไม่เท่ากันไม่ได้

พอดีช่วงนี้กำลังเขียน Ruby เพื่อจัดการข้อความภาษาไทย และพยายามออกแบบให้จัดการกับภาษาอื่นๆ ได้ด้วย ก็เลยต้องเก็บทุกอย่างไว้เป็น UTF-8 จะได้ไม่เสียเวลาแปลงข้อมูล เสร็จแล้วทีนี้จะต้องเข้าถึงตัวอักษรแต่ละตัวเพื่อคำนวณค่าอะไรบางอย่าง จะใช้ [] ก็ไม่ได้แล้ว เพราะจะได้ตัวอักษรไม่ตรงตัว สุดท้ายเลยต้องไปหา gem ที่ช่วยจัดการ UTF-8 มาลองใช้ด้วย เท่าที่ลองหาดูก็เจอ

  • icu4r เป็น binding ที่ทำให้ Ruby ใช้ความสามารถของ ICU ได้ โดยสร้าง class ใหม่ชื่อ UString มาใช้โดยเฉพาะ ดูท่าทางจะใช้ได้ดี แต่ก็มีข้อเสียอยู่ที่ติดตั้งยาก ต้องลง ICU ไว้ในระบบก่อน สุดท้ายเลยเลิกไป
  • utf8proc เป็น module อีกอันหนึ่ง ที่เพิ่มส่วนขยายให้คลาส String ซึ่งก็มีข้อจำกัดในฟังก์ชันการทำงาน แถมยังไม่ค่อยมีเอกสารเท่าไหร่
  • character-encodings อันนี้ไปเจอทีหลังสุด ฟีเจอร์ต่างๆ ก็ดูดี ใช้งานไม่ยุ่งยาก (แต่อาจจะหาเอกสารยากเหมือนกัน) แต่คนเขียนพยายามบอกว่ามันคือส่วนหนึ่งที่อาจจะรวมเข้าไปใน Ruby 2.0 เลยเลือกใช้อันนี้

การใช้งานก็ไม่ยาก ลองดูตามตัวอย่างนี้ได้เลย

require 'rubygems'
require 'encoding/character/utf-8'
s = +"สวัสดีครับ"
a = Array.new
s.each_char {|c| a << c}

แค่นี้เราก็แยกตัวอักษรแต่ละตัวจาก s ไปไว้ในอะเรย์ a ได้เลย ตัวอักษรแต่ละตัวก็ยังเก็บในฐานะ String เหมือนเดิม ถ้ามองในแง่ความสะดวกแล้ว การทำแบบนี้ก็ง่ายดี แต่ดูแล้วมันต้องแปลงไปแปลงมาอยู่หลายรอบเหมือนกัน

Tags: ,

28 Jun 07 ActiveScaffold

วันก่อนลองค้นไปค้นมา เจอ ActiveScaffold ซึ่งเป็น plugin สำหรับ Ruby on Rails ซึ่งสนับสนุน Ajax และสามารถปรับแต่งวิธีการแสดงผลต่างๆ ของ Scaffold ได้ง่ายๆ เลยกำลังคิดว่าจะเอามาใช้กับระบบที่กำลังทำอยู่

Tags: ,