โดย
อ.ธนะพันธ์ อินทรเกสร
1/1/12
บทที่ 1 เริ่มรู้จัก Ruby บน Sketchup
ผมทำการสอน C# มาหลายปี พบว่า C# เป็นภาษาที่ง่าย และมี Syntax ที่เข้าใจง่าย แต่เป็น Syntax Strong Type ทำให้การเขียนโปรแกรมช้า แต่ถ้าทำโปรแกรม ขนาดใหญ่มีการควบคุม และตรวจสอบได้ง่าย
ผมเริ่มมาดู Sketckup เนื่องจาก มีโครงการคิดราคาจากแบบ 3D และมีคนแนะนำว่า Sketckup มีการใช้อย่างแพร่หลาย น่าจะมีโปรแกรม คิดราคาแบบเดียวกัน กับบน Autocad หรือ Revit
ผมจึงได้เริ่มดู Sketckup พบว่า ระบบภาษาของ Sketckup เป็นภาษาเก่าแก่ ภาษาหนึ่ง คือ ภาษา Ruby เป็นภาษา Object Oriented Programming ที่ดีในยุกต์เก่า ภาษา Ruby ที่มีชื่อเสียงมานาน คือ Ruby on Rails เป็นภาษาที่ใช้ ทำ Web แบบเดียวกับ ภาษา PHP เราก็จะพบตัวอย่างจำนวนมากที่ใช้ Ruby ในการสร้างโปรแกรมด้วย Ruby ใน Sketchup เป็นภาษาแบบInterpreter ไม่ใช่แบบ Compiler วิธีการเขียนโปรแกรมก็จะพลิกแพลง ได้มาก เหมือน กับ ภาษาเว็บเพจ PHP ที่ใช้ Dynamic Code (โปรแกรมเปลี่ยนแปลง Code ระหว่างที่ทำงาน) ข้อเสียคือช้า และการ Debug จะไม่ค่อยมี Tool ที่ดีเมื่อเทียบกับ Compiler เช่น Visual Studio
ปัญหาคือ Ruby มี Syntax ที่ไม่ค่อยคุ้ยเคยกับโปรแกรมในปัจจุบันทั้ง
คนที่เป็น C# จะทำโปรแกรม บน Ruby โดยไม่ยากได้อย่างไร
มาดู Code แรกของ โปรแกรม Hello World ทั้ง 2 แบบ
C# | Ruby |
using System; using System.Collections.Generic; using System.Linq; using System.Text;
namespace helloWorld { class Program { static void Main(string[] args) { Console.WriteLine("Hello World"); } } }
| puts “Hello World” |
จะเห็นว่า Ruby เขียนแบบง่ายๆ สั้นๆ การจบคำสั่งใช้ขึ้นบรรทัดใหม่ ในการแสดง ผล ซึ่งเป็นธรรมชาติของโปรแกรม ชนิด Weak Type และ เป็น Interpreter ซึ่งเที่ยบกับ AutoLisp ก็จะเป็น (Print “Hello World”) คล้ายๆกัน
ข้อสังเกตุ ในโปรแกรมของ C# จะมีการแสดง Class สำหรับการเรียกใช้ ขณะที่ Ruby จะเป็นการเรียกโดยตรง มีลักษณะแบบเดียวกับภาษา Basic ในยุกต์แรก
ที่น่าสนใจคือ Ruby มีการจัดการแบบภาษาสมัยใหม่มีการจัดการเรื่อง Class และ การจัดการ ตัวแปร (Variable ) และการจัดการ Function Method ใน Class หรือไม่ คำตอบคือ มี Ruby ได้มีการ กำหนด ในรูปแบบของ Class ได้เหมือนกัน แต่ขณะเดียวกันก็ทำงานแบบคำสั่งโดยตรง ก็ได้ หลายคนที่เขียนโปรแกรมครั้งแรกจะชอบแบบนี้มากเพราะสร้าง โปรแกรมได้เร็ว แต่ถ้าเขียนกันเป็น พันบรรทัดแล้วก็ ไม่สนุกแน่ เพราะการ ไล่โปรแกรมจะยากมาก
แต่ข้อดีของ Ruby คือความคล่องตัวในการคำนวน ปรับ syntax
ข้อเสียคือ ภาษาไม่ควบคุมการ เข้าหา ตัวแปร และ Function,Method ของผู้เขียนโปรแกรม จะยากในการ Debug
ข้อดีของ C# คือ เป็นภาษาที่มีการจัดระเบียบ อย่างดี ในเรื่องของ Class สำหรับการเขียนโปรแกรม ขนาดใหญ่ และมีตัวช่วยเขียน Debugger ที่ดีที่สุดในโลก(Microsoft ทำดีจริงๆ)
ข้อเสีย ต้องวางแผนการเขียนโปรแกรมให้ดี และโชคไม่ดีคือ Support Sketckup
มีคนถามเสมอว่าแล้วบน Mac Osx, Iphone มี C# หรือไม่ คำตอบคือมี Mono project และฟรี ทดลองใช้แล้ว ใน Console Mode ใช้เหมือนกับใน Visual studio แต่ใน Form การเรียก control จะต่างกัน แต่ก็ทำงานแบบเดียวกัน
Syntax ภาษาของ Ruby
Syntax ภาษาของ Ruby มีมากกว่า C# มากเพื่อความคล่องตัวของผู้ใช้งาน ดูได้จาก Wikipedia จะมีคำอธิบาย อยู่พอสมควร แต่ เพื่อความมีระเบียบ ในแบบ C# จะใช้ Syntax ที่เขียนโปรแกรมเพื่อใช้งาน ไม่มาก และจะเข้าใจได้ง่ายกว่า โดยที่ไม่ต้องเข้าใจทั้งหมด เพราะการเขียนโปรแกรมที่เข้าใจง่าย ไม่ควรใช้เทคนิค ซับซ้อน
Note ข้อเข้าใจในภาษาเขียนของผม ถ้าผมใส่ <abc> หมายถืงตรง abc จะเป็นชื่อที่อาจจะเป็นชื่อ โปรแกรม หรือตัวแปรที่ตั้งเอง หรือชื่อใดๆ
ตัวแปร Variable
ตัวแปรใน ภาษา Ruby เป็นตัวแปรที่มีทั้งระบุและไม่ระบุ Type
ชนิดตัวแปร | รูปแบบ |
ตัวแปร local สำหรับใช้ใน Function หรือ Method | ใช้ตัวอักษรตัวเล็ก อยู่ภายใต้ def..end def <function> len=10.0 end len จะเป็นตัวแปรที่มีค่าเฉพาะใน def <function> จนจบ ที่ end
|
ตัวแปร Global สำหรับส่งต่อ ระหว่างโปรแกรม หรือติดตลอดโปรแกรม | ใช้ $<ชื่อ> $price =20.0 $price จะมีค่า และแก้ไขได้ตลอดโปรแกรม มีค่าเดียว
|
ตัวแปร คงที่ หรือ constant ตัวแปรนี้จะเปลี่ยนค่าไม่ได้ และ มีค่าตลอดโปรแกรม | ใช้ตัวอักษรใหญ่ Capital เช่น PI=3.14159
|
ตัวแปร แบบ Instant ใช้ใน Class | ใช้ เครื่องหมาย @ นำหน้า เช่น @height=2.0
|
ปัญหาหนึ่งของ Ruby คือไม่ควบคุม เรื่องชนิด Type ของตัวแปร ทั้งเริ่มต้น และระหว่างทำงาน อันนี้เป็นปัญหาในการ Debug มาก เพื่อความเป็นระเบียบ
จะต้องกำหนด Syntax ต่อท้าย ให้ง่ายต่อการจดจำ เช่น _i,_r,_s
count_i หมายถึง ตัวแปรแบบตัวเลขเต็ม
dist_r หมายถึงต้วแปร ทศนิยม
name_s หมายถึง ตัวแปรอักษร
ไม่นั้นเวลาแก้ไขจะงงมากเมื่อโปรแกรมมีขนาดใหญ่แล้วต้องแก้พร้อม Debug
การสร้าง Function หรือ Method
การสร้าง Function เป็นแบบ ง่ายๆโดยกำหนด
def <ชื่อ Function>
<เนื้อโปรแกรม>
end
^ จบโปรแกรม
สำหรับการส่งค่าตัวแปร Parameter ให้ส่งด้านหลังใน วงเล็บ
def compute_volume(w,l,d) W*l*d End
|
เทียบกับ C#
private double compute_volumn(double w,double l,double d) { return w*l*d; } |
การคืนค่าหรือ Return value จะต้องทำโดยเป็นค่าสุดท้ายของการคำนวน
ในกรณีนี้จะเป็น ค่าที่เกิดจากผลการคูณ ของ w*l*d อันเป็นปริมาตรลูกบาตร์
ถ้าต้องการคำนวนโดยการกำหนด ตัวแปร Local ก็สามารถทำในรูปแบบนี้
def compute_volume(w,l,d) v_r=W*l*d end_R
|
ตัวแปร v จะใช้ในโปรแกรม compute_volume เท่านั้น
เทียบกับ C#
private double compute_volumn(double w,double l,double d) { double v= w*l*d; return v; }
|
โปรแกรมที่เป็น function ทำงานโดยการ Pass by value
คือส่งค่า แล้วไม่รับกลับ การส่งกลับ ดังนั้น Function จะรับค่ากลับได้เพียง
ครั้งเดียว ซึ่งอาจจะส่งกลับเป็น Class หรือ Array ที่มีหลายค่าก็ได้
เช่น
def area_perimeter( w , l) area_r = w*l peri_r = (w+l)*2 [area_r,peri] end |
เวลาใช้งาน ค่าก็จะใส่ลงในตัวแปรตามลำดับ
myarea_r,myperi_r= area_perimeter( 2, 3)
|
ปัญหา คือ Ruby จะไม่เช็คว่า การรับค่า ครบหรือไม่ เป็นเรื่องของ ผู้เขียนต้อง ตรวจเอง
สำหรับ C# จะทำแบบนี้ไม่ได้ เนื่องจาก C# จะส่ง Return ได้ทีละตัว แต่ส่ง ค่าไป Reference จะได้กลับมา
double area_perimeter(ref double peri, double w, double l) { double area= w*l; peri = (w+l)*2; return area; } |
การเขียนโปรแกรม Ruby แบบ C# เริ่มได้แล้ว
ถ้าไม่ต้องคิดถึงการสร้าง Class โปรแกรมง่ายๆ ก็สามารถทำงาน ได้แล้ว เช่น
ตัวอย่างโปรแกรมคำนวน พื้นที่รั้ว
มีโจทย์อยู่ว่า มีพื้นที่เป็นรูปหลายเหลี่ยม ต้องการคำนวนพื้นที่รั้วถ้ารั้วสูง 2 เมตร เพื่อนำพื้นทีไปคำนวนงานต่อไป
มาดู Flowchart
[จำนวนจุด,ตั้งค่าระยะรวม=0] V [เปลี่ยนเป็น LineSegment] V <ทำที่ละ Segment จนจบ> --------à[พื้นที่=ระยะรวม*ความสูง]->จบ V ^ [ระยะรวม+=คิดระยะทางแต่ละ LineSegment]
|
โดยการสร้าง Function ที่ชื่อว่า wdist สำหรับคำนวนระยะทาง
และให้ Loop หลักทำการคำนวนรวมค่า
ถ้าเป็น C# จะเขียนแบบนี้
class Program { static double wdist(double x1, double y1, double x2, double y2) { double dd = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1); return Math.Sqrt(dd); } static void Main(string[] args) { // x as 0 , y as 1 in second Array location double[,] pts = new double[5, 2] { { 0, 0 }, { 10, 0 }, { 10, 5 }, { 0, 5 }, { 0, 0 } }; double totaldist = 0; double wallh = 2.0;// wall height for (int i = 0; i =< 3; i++) { totaldist = totaldist + wdist(pts[i, 0], pts[i, 1], pts[i + 1, 0], pts[i + 1, 1]);
} double area1=totaldist*wallh; Console.WriteLine("Total dist,area="+totaldist.ToString()+","+area1.ToString()); } } |
เราลองเปลี่ยนเป็น Ruby โดยใช้ Style C#
def wdist(x1,y1,x2,y2) dd_r=(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1) Math.sqrt(dd_r) end
pts = [[0,0],[10,0],[10,5],[0,5],[0,0]] totaldist_r=0.0 wallh_r=2.0 i =0 for i in (0..3) totaldist_r=totaldist_r+wdist(pts[i][0],pts[i][1],pts[i+1][0],pts[i+1][1]) end area1_r=totaldist_r*wallh_r puts "Total dist="+totaldist_r.to_s+","+area1_r.to_s
|
ข้อสังเกตุ
มีตัวแปรของ C# จะกำหนดเป็น Strong Type โดยกำหนดเป็นตัวแปร แบบ double และกำหนด ตัวแปรเป็น Array
Array ของ C# ต้องกำหนดการใช้งานโดย new
double[,] pts = new double[5, 2] { { 0, 0 }, { 10, 0 }, { 10, 5 }, { 0, 5 }, { 0, 0 } };
|
การนำค่าตัวแปรมาใช้จะเป็น
x1=pts(0,0)
Array ของ ruby ไม่ต้องกำหนด type และขนาด
pts = [[0,0],[10,0],[10,5],[0,5],[0,0]]
|
การนำค่าตัวแปรมาใช้
x1=pts[0][0]
Flow control สำหรับโปรแกรม
ใน C# กับ Ruby เกือบจะเหมือนกัน
For loop ของ C#
for (int i = 0; i <= 3; i++) { totaldist = totaldist + wdist(pts[i, 0], pts[i, 1], pts[i + 1, 0], pts[i + 1, 1]); }
|
For loop ของ Ruby
i =0 for i in (0..3) totaldist_r=totaldist_r+wdist(pts[i][0],pts[i][1],pts[i+1][0],pts[i+1][1]) end
|
การควบคุม Flow โดยใช้ IF
ใน C# กับ Ruby เหมือนกัน จะ ใช้ if และตัวเทียบตรรก ได้แก่ <,>,==,!=,>=,<=
== หมายถึงเท่ากับ และ !=คือไม่เท่า
if(i<10) { <เนื้อโปรแกรม> }else { <เนื้อโปรแกรม> } |
ใน ruby
if (i<10) <เนื้อโปรแกรม> else <เนื้อโปรแกรม> end
|
การ Run โปรแกรม ใน Sketchup
เขียนโปรแกรม ลงใน Notepad แล้ว File->Save
c:\test.rb
ไปที่ เมนู ของ Sketup -> Window->Ruby console
พิมพ์ load “c:/test.rb”
สังเกตุ จะใช้ เครื่องหมาย ‘/’ แทน ‘\’ ในการเรียกชื่อ File
โดยสรุป
การเขียนโปรแกรมด้วยภาษา ruby เริ่มต้นง่าย แต่การ เขียนโปรแกรมขนาดใหญ่ ต้องมีระเบียบมากกว่านี้ ซึ่งจะบอกในตอนต่อไป