วันพฤหัสบดีที่ 30 เมษายน พ.ศ. 2558

Defining class in Scala

บทความในโพสนี้เป็นเรื่องการประกาศ class และการสร้าง instance ครับ ภาษา Scala เป็นทั้ง Object Oriented แหละ Functional  ดังนั้นเราควรทำความรู้จักกับวิธีการสร้างและนำไปใช้  เนื่องจาก blog นี้ผมตั้งใจจะเน้นเรื่องภาษาอย่างเดียว  ดังนั้นจะขอไม่ลงรายละเอียดเกี่ยวกับเรื่อง Object Oriented Programming

การประกาศ class ใน Scala ทำได้ดังนี้
class Point {
    var x;   //public
    var y;  ///public
}

ในกรณีนึ้เราประกาศ class Point ที่มี x และ y เป็นสมาชิกอยู่ ​(instance member)  x และ y เป็น public โดยอัตโนมัติ  ดังนั้นเราสร้างเข้าไปเปลี่ยนแปลงค่า x และ y ได้ เช่น

def main(args: Array[String]) {
    val p = new Point()  //สร้าง instance ของ Point
    p.x = 10
    p.y = 20
  }

เราสามารถประกาศ constructor ให้กับ class ได้โดยต่อไปนี้

จากในรูปจะเห็นว่าเราสร้าง instance ของ Point มาสองตัวคือ p และ p1  โดยที่เรา กำหนดค่า x กับ y ของ p หลังจากสร้าง instance

val p = new Point() //สร้าง instance
p.x = 10  //set x เป็น 10
p.y = 20  //set y เป็น 20

สำหรับ p1 เราหนดค่าเริ่มต้นให้กับ x และ y ตอนสร้าง instance เลย

val p1 =new Point(1,2)

    
ทีนี้มาดูวิธีประกาศ constructor กัน

class Point {
   var x : Int = _
   var y : Int = _
   
   def this(x:Int, y:Int) {
     this()  //จำเป็นต้องเรียก default constructor ในบรรทัดแรก
     this.x = x
     this.y = y
   }
}

เราประกาศ constructor เหมือนกันกับ เมทธอด แต่ใช้ชื่อว่า this  รวมถึง x:Int และ y:Int เป็น parameter  
สังเกตุว่าเราต้องเรียก default constructor --> this() ในบรรทัดแรก ไม่เช่นนั้นจะ compile error
เราไม่จำเป็นต้องประกาศ default constructor เพราะ Scala จะทำให้เราโดยอัตโนมัติ

สำหรับตัวอย่างต่อไปนี้ เราประกาศ contructor ที่รับแค่ x:Int  เราไม่ได้เรียก default constructor แต่เรายังจำเป็นที่จะต้อง เรียก constructor ตัวใดตัวนึงอยู่ดี

class Point {
   var x : Int = _  //set ค่าเริ่มต้นของ Int (0)  ให้ x
   var y : Int = _

   def this(x:Int) {
     this(x, 1) //เรียก constructor อีกตัวหนึ่ง
   }

   def this(x:Int, y:Int) {
     this()  //จำเป็นต้องเรียก default constructor ในบรรทัดแรก
     this.x = x
     this.y = y
   }
}

ในเมทธอด main  เราพิมพ์ค่าของ x และ y จาก ออกมาหลังจากรันโปรแกรม

x:10, y:20

x:1,  y:2

สังเกตุว่า การใช้ println เราสามารถใช้ variable ใน string ได้โดยการใช้

s"...${x}...."  โดยที่ x เป็นตัวแปร  และเราต้องมี s นำหน้า "" ในตัวอย่างของเราใช้

val p1 =new Point(1,2)
println(s"x:${p1.x}, y:${p1.y}")    

สำหรับการประกาศ  x และ y ใน class Point จะสังเกตุได้ว่าเราใช้

var x : Int = _

โดยที่ _  เป็นค่าเริ่มต้นของ Int    สมมิตว่าเราประกาศค่า boolean ดังนี้

var a : Boolean = _

a จะเก็บค่าเริ่มต้น (default value) ของ Boolean นั่นก้อคือ false นั่นเอง

สำหรับบทความต่อไปเรายังคงดูเรื่อง class และ instance กันต่อไปครับ

วันอังคารที่ 28 เมษายน พ.ศ. 2558

Declare variable using val

เรื่องต่อไปเกี่ยวกับการใช้ตัวแปรคือ val  วิธีการประกาศตัวแปรคล้ายๆ กับ var  คือ

val [name] : [type] = [initial value]

def test() {
    val x : Int = 1
    val y : Double = 1.0
    val z  = true

}

การประกาศตัวแปรโดยใช้ val เหมือนกับการประกาศตัวแปร final หรือ readonly ใน java หรือ c# นั่นเอง  เพียงแต่เราสามารถประกาศได้ในเมทธอด หรือในคลาสก้อได้

class Point {
   val x = 10
   val y = 20
}

เราจะต้องกำหนดค่าเริ่มต้นให้เสมอ และไม่สามารถเปลี่ยนแปลงค่าหลังจากนั้นได้อีก เช่น

val x : Int = 1
// x = 10   --> compile error

ทีนี้ทำไมต้องมี val ด้วย ในเมื่อเราสามารถใช้ var ได้อยู่แล้ว   คำตอบก้อคือเราไม่อยากจะเปลี่ยนค่าอีกหลังจากกำหนดค่าเริ่มต้นเรียบร้อยแล้ว ลองมาดูตัวอย่างกัน

val x = sum(1, 2)
val y = sum(3, 4)

// x = 10 --> compile error

val z = sum(x, y)

def sum(a:Int, b:Int) : Int = {
   return a + b
}

จากตัวอย่างข้างต้นจะเห็นว่าเราไม่ต้องจะเปลี่ยนค่าของ x, y และ z  เราต้องการเก็บค่าที่ได้มาจากเมทธอด sum เท่านั้น  อีกอย่างหนึ่งก้อคือ  a  และ  b ในเมทธอด sum เป็น val โดยอัตโนมัติเช่นกัน   compiler จะจัดการใส่ val  ให้เราเอง  ดังนั้นเราไม่สามารถเปลี่ยนค่า  (reassign value)  ให้กับ a และ b  ได้

def sum(a:Int, b:Int) : Int = {
   // a = 10 --> cannot reassign
   return a + b
}

เราไม่สามารถประกาศให้ parameter ในเมทธอดให้เป็น var หรือ val เพราะมันเป็น val โดยอัตโนมัติอยู่แล้ว

//compile error
def sum(var a:Int, val b:Int) : Int = {
   // a = 10 --> cannot reassign
   return a + b
}

สาเหตุที่  parameter เป็น val เพราะ Scala คิดว่า parameter ที่รับมาไม่ควรจะเปลี่ยนแปลงได้ เนื่องจากผู้ที่เรียกใช้อาจจะไม่ได้คิดว่าเมทธอดจะเปลี่ยนค่าที่ส่งมาให้  (side effect method)  ดังนั้นเพื่อความปลอดภัย Scala จึงทำให้เป็น val โดยอัตโนมัติ

สำหรับหัวข้อต่อไปที่เราจะนำมาทำความรู้จักคือ class และ instance  ใน  Scala

วันจันทร์ที่ 27 เมษายน พ.ศ. 2558

Local Variable in Scala

เราสามารถประกาศตัวแปร (local variable) ใน Scala โดยใช้ syntax ดังต่อไปนี้

var {name} : {data type} = {initial value}

var x : Int = 0
var y : String = "John"
var z : Double = 1.0
var p : Boolean = true

การประกาศตัวแปรเราจะต้องกำหนดค่าเริ่มต้นให้เสมอ  ถ้าเราไม่ได้กำหนดค่าเริ่มต้นจะพบกับ compile error ดังนี้

"local variables must be initialized"


อย่างที่ได้กล่าวไว้ในบทความก่อนหน้านี้ว่า  Scala  เป็นภาษาที่ยืดหยุ่นมาก ดังนั้น ในบางครั้งการประกาศตัวแปร เพื่อความสะดวกเราไม่จำเป็นต้อง ประกาศชนิดข้อมูล (data type) ก้อได้ เช่น

x = 0
y = "John"
z = 1.0

compiler รู้ว่า  x เป็นตัวแปรชนิด interger,  y เป็นตัวแปรชนิด  string  และ z เป็นตัวแปรชนิด double โดยอัตโนมัติ  ทีนี้ถ้าหากว่าเราไป เปลี่ยนชนิดของตัวแปร  x  ให้เป็น double

x = 1.0

compiler จะฟ้องทันทีว่า

"type mismatched; found: Double(1.0) required: Int

เนื่องจากในตอนแรกเราประกาศให้ x เป็นตัวแปรชนิด integer เราไม่สามารถเปลี่ยนชนิดข้อมูลให้เป็น double หรืออย่างอื่นได้ในตอนหลัง อย่างไรก้อตาม เราสามารถเปลี่ยนค่า x ได้ ตราบเท่าที่มันยังเป็น integer อยู่

x = 1 //ok


สำหรับการใช้ parameter ก้อคล้ายๆ กับการประกาศตัวแปร เพียงแต่ไม่ต้องกำหนดค่าเริ่มต้นให้

def sum(a:Int, b:Int) : Int = {
    return a + b
}

เราได้ประกาศเมทธอด sum ขึ้นมาโดยรับ parameter 2 ตัวคือ a และ b  ทั้งคู่เป็น integer   เมทธอดนี้บวกค่า  a และ b แล้วคืนค่า integer กลับไป

var x = sum(1, 2)

เราประกาศตัวแปร x และกำหนดค่า เริ่มต้นโดยการเรียกใช้ เมทธอด sum   ท้ายที่สุดแล้ว  x จะเก็บค่า  3 นั่นเอง




ในบทความต่อไปเราจะมาดูกันต่อว่าการใช้ val จะเป็นอย่างไร แตกต่างจาก var  ตรงไหนบ้าง








วันอาทิตย์ที่ 26 เมษายน พ.ศ. 2558

Hello World

เอาล่ะคราวนี้มาถึง Hello World กันซะที ก่อนอื่นให้ ดาวน์โหลดและติดตั้ง Java และ Eclipse for Scala ก่อนนะครับ คลิกไปตามลิงค์ต่อไปนี้ได้เลยครับ

https://java.com/en/download/

หลังจากติดตั้งเสร็จเรียบร้อย (ผมใช้ Java 8.0, Eclipse Luna) ให้รัน Eclipse ขึ้นมาแล้วทำตามดังต่อไปนี้

1. เปิด Package Explorer ขึ้นมา
2. ใน Package Explorer ให้ New Scala Project ตั้งชื่อโปรเจ็กว่า Test
3.  ใน Package Explorer เปิด Test และ src แล้วเลือก New--> Scala Object  ตามรูป





4. ในช่อง Name ให้ตั้งชื่อว่า  Hello  แล้วกด Finish  (เราจะได้ไฟล์ Hello.scala)
5. พิมพ์  ภายใน ​object Hello ตามรูป




6. ที่ ​​​Menu Bar --> Run --> Run As --> Scala Application  จะเป็นว่าเราพิมพ์คำว่า ​Hello World ออกมา



เสร็จเรียบร้อยแล้วครับ Hello World  ของเรา  ทีนี้มาดูว่าเราทำอะไรกันไปบ้าง
ก่อนอื่นเลยเราสร้างไฟล์ Hello.scala ขึ้นมาโดยตั้งชื่อว่า object Hello  ในภาษา Scala เรามีทั้ง class และ object นะครับ  สำหรับ class ก้อเหมือนกับภาษาอื่นทั่วไป คือเป็นแม่แบบ (definition) สำหรับการสร้างวัตถุ (instance)   

ใน Scala ไม่มี keyword static ถ้าหากเราต้องการใช้งานมัน เราจะต้องไปประกาศใน object (keyword) ครับ ในที่นี้เราต้องการประกาศ method main  ทุกอย่างใน Scala เป็น OO ดั้งนั้น static/class variable/class method จึงไม่มี  อย่างไรก้อตาม Scala ใช้ singleton object แทน 

//singleton object
object Hello {

}

ทีนี้การประกาศจุดเริ่มต้นของโปรแกรมเราใช้  main ฟังก์ชั่น  แล้วพิมพ์คำว่า  ​​Hello World ออกมาโดยใช้ println  สังเกตุว่าเราไม่มี semicolon เลย

def main(args: Array[String]) {
  println("Hello World")
}

Scala เป็นภาษาที่ยืดหยุ่นมาก เราจะมี semicolon  หรือไม่ก้อได้ รวมถึงวิธีการประกาศฟังก์ชั่นก้อมีอีกหลายรูปแบบ เอาไว้ โพสต่อไปเราค่อยมาต่อกันถึงการสร้าง instance และการใช้ตัวแปรครับ

ก่อนจะเริ่ม Hello World Scala!!!

ก่อนอื่นต้องขอกล่าวคำว่าสวัสดีครับ กับทุกคนที่เข้ามาอ่าน บทความต่างๆ ใน  Blog นี้ เนื้อหาจะเป็นเรื่องเกี่ยวกับวิธีการเขียนโปรแกรมด้วยภาษา Scala ซึ่งกำลังจะเป็นภาษาใหม่ที่มีอนาคตมากทีเดียวเมื่อเทียบกับ Java หรือ C#  (ลองค้นหา Scala developer salary ดูครับ)

ผมเริ่มใช้ Scala ประมาณสองปีที่แล้ว (2013) โดยที่มีพื้นฐานมาจาก C# (Microsoft) ในครั้งแรกเลย ภาษานี้ยากมาก ไม่ว่าตัวภาษาเอง หรือ เครื่องไม้เครื่องมือที่จะใช้มาเขียนโปรแกรม  รวมถึงระบบปฎิบัติการด้วย (ต้องเขียนโปรแกรมบนเครื่อง Mac จากเดิมอยู่บน Microsoft Windows)  แต่หลังจากทนมาได้ซัก 2 อาทิตย์ ก้อเริ่มคุ้นเคย และรู้สึกไม่ยากอีกต่อไป จากนั้นก้ออยู่ตัวครับ ผมคิดว่าเรื่องการปรับตัวเป็นสิ่งสำคัญ ทุกๆ ภาษาที่เราเริ่มใหม่มันมักจะยากเสมอ แต่ไม่ว่าอย่างไร คนอื่นเขาทำกันได้ แล้วทำไมเราจะทำไม่ได้บ้างล่ะ

เรื่องมันเกิดมาจากงานที่ผมทำ เป็นงานพวก Search engine ที่ต้องการอัตราการค้นหา (Throughput) ให้เร็วที่สุด (response time < 200 millisec) ประกอบกับปริมาณการค้นหาเยอะมาก ( > 200 requests /sec) ทำให้เราเริ่มมีปัญหากับ Microsoft Technology ดังนั้นจึงคิดกันว่าทิ้งไว้คงไม่ได้แล้วแล้วต้องหาอะไรมาทดแทน ตอนหลังๆ เราเพิ่มจำนวน Server แต่คำถามก้อคือเพิ่มเท่าไหร่ถึงจะพอ  หลังจากนั้นก้อเริ่มไปค้นหาว่าใช้อะไรดีในที่สุดมาเจอกับ ภาษา Scala (ย่อมาจาก  ​Scalability) หลายๆคนที่ใช้งานภาษานี้อยู่ต่างก้อพรรณาถึงข้อดีเลยตัดสินใจว่าภาษานี้แหละคือคำตอบ

หลังนั้นอีกหกเดือน Search engine ตัวใหม่ที่ทำมาจาก Scala ก้อเริ่มนำมาใช้งานจริง โดยคราวนี้ไปรันบนระบบปฎิบัติการ Linux ปรากฎว่า  ใช้งานได้ดีกว่าที่คาดมากๆ  response time < 100 millisec, througput > 800 requests/sec. หลังจากใช้งานไปหนึ่งเดือนผลตอบแทนทางธุระกิจครอบคลุมค่าใช้จ่ายในการพัฒนาทั้งหมด (เงินเดือนโปรแกรมเมอร์, ค่าคอมพิวเตอร์ ​Mac, ค่า Server ...)

เนื่องจากผมเห็นข้อดีของภาษานี้จึงอยากให้นักพัฒนาในประเทศได้รู้จักและนำมาใช้  แต่เป็นที่น่าเสียดาย ตำราหรือว่าข้อมูลต่างๆ ส่วนใหญ่แล้วจะเป็นภาษาอังกฤษ ผมจึงเขียน  Blog นี้ขึ้นมา เพื่อที่จะถ่ายทอดในรูปแบบภาษาไทยให้ทุกคนได้อ่านกัน และเพื่อความง่ายบทความแต่ละเรื่องจะใช้เวลาอ่านไม่เกิน 5 นาที