2011/11/10

F# - #2

สวัสดีครับ วันนี้เราจะมาฝึกเขียนภาษา F# กันอีกเช่นเคย แต่จะเป็นเรื่องอะไร ลองทายดูสิครับ
...
วันนี้เราจะมาเขียนฟังก์ชันกันครับ !!!!
อ่านถูกแล้วหล่ะครับ มันคือฟังก์ชัน นั้นแหละครับ
บางคนอาจจะงง ยังไม่ทันไรก็ขึ้นฟังก์ชันแล้ว ?
จริง ๆ แล้วฟังก์ชันในภาษา F# นั้นสร้างไม่ยากเลยครับ เพราะว่าใช้คำสั่ง let เหมือนกัน

let myFun() = 5
let a = myFun()
printfn "%A" a

เหมือนกันเลยครับ แต่ต้องใส่ () ต่อท้ายเท่านั้นเอง เราก็จะได้ myFun เป็นฟังก์ชันแล้ว... เย้

ต่อไปมาลองสร้างฟังก์ชันที่มีการรับค่าเข้าไปดูครับ

let add a b = a + b
let r = add 6 4
printfn "%A" r

เป็นยังไงบ้างครับ ง่ายใช่ไหมหล่ะครับ

แล้วถ้าฟังก์ชันมีหลายบรรทัดหล่ะ จะเขียนยังไงดี ?

ก่อนอืนเลยต้องบอกว่า scope ใน F# จะใช้ย่อหน้าครับ เช่นในภาษา C/C++, C# จะเป็น { } ใน Object Pascal เป็น begin end; เป็นต้น

let f x =
    let r1 = x * x
    let r2 = r1 + 20
    r2
printfn "%A" (f 6)

จะเห็นว่าคำสั่งที่อยู่ในย่อหน้า ตั้งแต่ let r1 จนถึง r2 จะเป็นคำสั่งในฟังก์ชัน f ครับ

ลองมาดูกันทีละบรรทัดนะครับ
let f x =

หมายถึง สร้างฟังก์ชัน f ที่รับค่า x เข้าไป
    let r1 = x * x
    let r2 = r1 + 20

คือการสร้างค่าคงที่ ที่อยู่ในฟังก์ชันครับ เพราะฉะนั้นเราจึงใช้ r1 กับ r2 ได้แค่ในฟังก์ชัน f เท่านั้น

    r2

คือการส่งค่ากลับออกมาให้ฟังก์ชันครับ คล้าย ๆ กับ return r2; ในภาษา C/C++, C# ฯลฯ

นอกจากนี้เรายังสามารถประกาศค่าคงที่ ที่ชื่อซ้ำกันในฟังก์ชันได้อีกด้วย

let f x =
    let r = x * x
    let r = r + 20
    r

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

let f(x) =
    let r = x * x
    let r = r + 20
    r
printfn "%A" (f(6))

นอกจากนี้ยังสามารถใช้ชื่อซ้ำกันใน scope ที่ซ้อนกันได้

let f x =
    let r =
        let r = x * x
        r + 1
    r * 2
printfn "%A" (f 3)

จะเห็นว่าตำสั่ง r + 1 จะหมายถึง r ที่เป็น x * x และ r * 2 จะหมายถึง r ตัวแรกที่อยู่หลัง let f x


Tuple คืออะไร ? http://en.wikipedia.org/wiki/Tuple

ลองดูตัวอย่างกันดีกว่าครับ
let (a, b) = (1, 2) // หรือ let a, b = 1, 2
printfn "a = %A" a
printfn "b = %A" b

เราจะได้ a = 1 และ b = 2 ครับ คิดว่าดูจากตัวอย่างแล้วน่าจะเข้าใจนะครับ

คราวนี้
let a = (1, 2)
printfn "%A" a

ลองรันดูนะครับ แล้วดูว่า a คืออะไร ?

ถ้ารันดูแล้วจะรู้ว่า a จะเท่ากับ (1, 2)

แล้วจะเอาค่าออกมายังไงหล่ะ ?
let a = (1, 2)
let x = fst a
let y = snd a
printfn "x = %A\ny = %A" x y

เราจะใช้ฟังก์ชัน fst เพื่อเอาค่าของตัวแรกออกมา และใช้ snd เพื่อเอาค่าตัวหลังออกมา ซึ่งฟังก์ชันทั้ง 2 ตัวนี้มีอยู่แล้วครับ แต่ถ้าใครจะเขียนเองก็ไม่ยากครับ
let fst(a, b) = a
let snd(a, b) = b

แต่ต้องใส่วงเล็บด้วยนะครับ จะเขียนเป็น fst a b ไม่ได้ เพราะ (a, b) มันคือ tuple ไงครับ

ลองดูตัวอย่างกันอีกหน่อย
let f a b = a + b
let x = f(4, 5)
printfn "%A" x

เราไม่สามารถเขียนแบบนี้ได้นะครับ เพราะ f จะต้องรับค่าเข้าไป 2 ค่า แต่ (4, 5) มันคือ ค่าเดียวครับ
จึงต้องเขียนเป็นแบบนี้
let f(a, b) = a + b
let x = f(4, 5)
printfn "%A" x

และแน่นอนครับว่าแบบข้างล่างนี้ก็ใช้ไม่ได้
let f(a, b) = a + b
let x = f 4 5
printfn "%A" x

เพราะว่า f รับค่าเข้าไปแค่ค่าเดียว คือข้อมูลแบบ tuple (a, b) แต่ f 4 5 หมายถึง ส่ง 4 กับ 5 เข้าไปให้ f


ต่อไปมาดูการละค่ากันครับ
let a = (1, 2)
let x, _ = a
printfn "%A" x

จะได้ x = 1 ครับ เครื่องหมาย _ (underscore) หมายถึงละค่าครับ เพราะฉะนั้นเลข 2 จังไม่ถูกเก็บเข้ามา

และ _ ไม่สามารถตั้งเป็นชื่อได้ เราจึงไม่สามารถ printfn "%A" _ ได้ครับ

2011/11/09

F# - #1

สวัสดีครับ วันนี้เราจะมาหัดเขียนโปรแกรมในภาษา F# กันครับ
ภาษา F# คืออะไร ? ลองดูที่ wikipedia นะครับ http://en.wikipedia.org/wiki/F_Sharp_(programming_language)
ก่อนอื่นเลยเราต้องมาลงเจ้า Compiler กับ IDE กันก่อนนะครับ
ตัว Compiler โหลดได้จาก http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/ หรือถ้าหาไม่เจอก็เข้า http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=18706 ก็ได้ครับ
ส่วน IDE ก็ใช้ Visual Studio 2010 Shell ครับ http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=115
แล้วก็อย่าลืมลง .NET Framework ด้วยนะครับ http://www.microsoft.com/download/en/details.aspx?id=17851
เอาหล่ะ เราลองมาเขียนโปรแกรมแรกกันเลยดีกว่า ลองทายสิว่าโปรแกรมอะไร...

ใช่แล้ว มันก็คือ Hello World นั้นเอง
ก่อนอื่นเลยก็เปิดโปรแกรม Visual Studio 2010 Shell สร้าง Project ใหม่นะครับ เลือกที่ F# Application แล้วกด OK โล้ดดด




แล้วเราจะได้ source code เปล่า ๆ ที่ comment 1 บรรทัด เขียนไว้ว่า
// Learn more about F# at http://fsharp.net

จะลบทิ้งก็ได้นะครับ

สำหรับคนที่เคยเขียนภาษาอื่นมาก่อนเช่น C# หรือ VB.NET อาจจะตกใจเพราะว่าไม่เจอ code อะไรเลย ปกติใน C# หรือ VB.NET เมื่อสร้าง project ใหม่แล้วจะมี template มาให้

เอาละครับ เรามาเขียน code กันเลย

ง่าย ๆ สั้น ๆ ครับ ไม่ต้องสร้าง class ไม่ต้องสร้าง function อะไรเลย แค่พิมพ์ลงไปว่า
printfn "Hello World"

ไม่ต้องตกใจครับ แค่บรรทัดเดียวครับ "code มีแค่บรรทัดเดียว"

เสร็จลองรันดูนะครับ ถ้ารันแบบ Debug (F5) จะมีหน้าต่างดำ ๆ โผล่ออกมาแล้วหายไป ให้รันแบบไม่ใช้ Debug (Ctrl + F5) แทนนะครับ



เป็นยังไงบ้างครับ สั้นดีใช่ไหมหล่ะครับ



เอาหล่ะครับ เรามาสร้างค่าคงที่กันดีกว่าครับ...

แน่นอนครับ ว่ามันคือ "ค่าคงที่"

เราก็เจอกันไปแล้วในโปรแกรมที่เขียนกันเมื่อกี้ ก็คือ "Hello World" นี่แหละ มันคือค่าคงที่ชนิด String นี่แหละครับ



และ!! เราจะใช้คำสั่ง let (ให้) ในการตั้งชื่อให้กับค่าคงที่ครับ
let s = "Hello World"

เราจะได้ s เป็นค่าคงที่ ที่เก็บ "Hello World" เอาไว้

ซึ่งแน่นอนว่า s เป็นค่าคงที่ !! เราจึงไม่สามารถเปลี่ยนแปลงค่า s ได้

นี่คือแนวคิดแบบ functional programming ครับ หรือก็คือ ทุก ๆ อย่างนั้นเป็นค่าคงที่ รวมถึง function ด้วย

เราคงเคยเจอกันมาเยอะแล้ว..

เคยเจอมาเยอะแล้วจริง ๆ ครับ ในวิชาคณิตศาสตร์ยังไงหล่ะครับ เช่น ถ้า a = 10 แล้วเราก็ไม่สามารถเปลี่ยนค่า a ได้ถูกไหมครับ



แต่ F# ไม่ได้เป็น functional language ซะดีเดียว เราจึงสามารถเปลี่ยนแปลงค่าได้

เราจะใช้คำสั่ง mutable (ไม่แน่นอน) ต่อท้าย let ครับ เพื่อให้เราสามารถเปลี่ยนแปลงค่าได้
let mutable a = 6

เราจะได้ a ที่แปลงร่างกลายเป็นตัวแปรแล้ว !

แต่ระวังอย่างหนึ่งนะครับ เครื่องหมาย = ไม่ใช่หมายถึง ให้ a = 6 ซะทีเดียว

เครื่องหมาย = คือเครื่องหมายกำหนดค่าให้ตั้งชื่อค่าคงที่ (ในคำสั่ง let) และเป็นเครื่องหมายทางตรรกศาสตร์

เช่นถ้าเราเจอ a = 4 โดยที่ไม่มี let แสดงว่า เครื่องหมาย = กำลังทำหน้าที่ตรวจสอบค่าว่า a เท่ากับ 4 รึเปล่า

เพราะฉะนั้นเราจึงไม่สมารถใช้ = เปลี่ยนค่าของ mutable ได้ แต่จะใช้เครื่องหมาย <- (น้อยกว่า + ขีด) แทน
let mutable a = 6
printfn "%A" a
a <- 10
printfn "%A" a

และแน่นอนว่า ตอนนี้ a มีชนิดข้อมูลเป็น int (จำนวนเต็ม) เราไม่สามารถเปลี่ยนค่าให้กลายเป็นอย่างอื่นได้ เช่น
a <- "Text"
a <- 3.2

ทำไม่ได้แน่นอนครับ



แล้ว... %A คืออะไร ?

คนที่เคยเขียนภาษา C/C++ มาก่อนจะรู้ได้ทันทีเลยว่าคืออะไร (รึเปล่า)

มันก็คล้าย ๆ กับ %d %f ในภาษา C/C++ นั้นแหละ

แต่ %A จะดีกว่าหน่อยนึง ก็คือเราจะใส่ค่าอะไรลงไปก็ได้ เดี๋ยวมันจะเรียกฟังก์ชัน ToString() ของค่านั้น ๆ ออกมาให้

2011/11/06

.NET Framework - #1 Hello World.

สวัสดีครับ หายหน้าหายตาไปนาน ลืมผมหรือยังครับเนี่ย ฮ่า ๆ ๆ

วันนี้เราจะมาเขียนโปรแกรมบน .NET Framework กันครับ จะใช้ภาษาอะไรเลือกกันตามสบายเลยครับ

.NET Framework คืออะไร ?
    .NET Framework ก็คือ platform ที่พัฒนาโดย Microsoft เพื่อที่จะให้การพัฒนาโปรแกรมทำได้ง่ายขึ้น โดยที่เวลา compile ตัว compiler จะแปล code ในภาษาที่เราเขียนเป็นภาษากลาง เรียกว่า MSIL เวลาเรียกใช้โปรแกรมตัว CLR ใน .NET Framework จะแปล MSIL ให้เป็นภาษาเครื่องอีกที

ก่อนอื่นเลยต้องลงโปรแกรม Visual Studio 2010 ก่อนครับ จะใช้เวอร์ชัน Express หรือจะเป็นเวอร์ชันทดลองใช้ก็ได้ครับ โหลดได้ที่ http://www.microsoft.com/visualstudio/en-us

ผมขอใช้ Visual Studio 2010 Pro Trial นะครับ




ลงเสร็จแล้วเราลองมาเขียนโปรแกรมง่าย ๆ กันครับ
เป็นโปรแกรมแสดงข้อความคำว่า Hello World. ผ่าน Console

C++/CLI
สำหรับภาษา C++/CLI นะครับ ให้สร้าง Project เป็นแบบ CLR Empty Project นะครับ แล้วสร้างไฟล์ .cpp ขึ้นมาหนึ่งไฟล์ อาจจะตั้งชื่อว่า main.cpp ก็ได้

using namespace System;

int main()
{
    Console::WriteLine("Hello World.");
    Console::ReadKey();
    return 0;
}


C#
ให้สร้าง Empty Project แล้วสร้าง Code ไฟล์ขึ้นมาใหม่นะครับ

using System;

class Program
{
    static void Main()
    {
        Console.WriteLine("Hello World.");
        Console.ReadKey();
    }
}

VB
ให้สร้าง Empty Project แล้วสร้าง Code ขึ้นมาเหมือนกันครับ แล้วก็อย่าลืมไปตั้งใน Project Properties เปลี่ยนตรง Application type เป็น Console.Application ด้วยนะครับ

Option Strict On
Option Explicit On

Imports System

Module Program
    Sub Main()
        Console.WriteLine("Hello World.")
        Console.ReadKey()
    End Sub
End Module

F#
สร้าง Project เป็นแบบ F# Application นะครับ
ในภาษา F# ผมขอใช้ printfn แทน Console.WriteLine นะครับ

open System

printfn "Hello World."
Console.ReadKey() |> ignore

2011/10/04

C++ - String

สวัสดีผู้อ่านทุกท่านครับ วันนี้ผมจะมาแนะนำ class ตัวหนึ่ง ที่คิดว่าจะทำให้การเขียนโปรแกรมง่ายขึ้น
และเพื่อให้เข้าใจเรื่อง class มากขึ้น

class ที่ผมจะมาแนะนำให้รู้จักคือ string

class string ใน C++ ไม่เหมือนกับ string ใน ภาษา C
ในภาษา C ตัวแปร string คือแถวลำดับของ char
แต่ string ใน C++ จะจัดการกับหน่วยความจำให้กับเราเอง เราไม่ต้องไปยุ่งกับมัน

ก่อนอื่นเลย เราจะต้อง include ไฟล์ที่จำเป็นเข้ามาก่อน คือ

#include <string>

string อยู่ใน namespace std เวลาจะประกาศ object เราจะต้องข้ึนต้นด้วย std

std::string s;

หรือจะประกาศ using namespace std; ไว้เลยก็ได้

using namespace std;


string s;

ลองมาดูฟังก์ชันที่ใช้บ่อยใน string กัน

string::size()
string::length()

ทั้งสองฟังก์ชันนี้จะ return ค่าความยาวของข้อความออกมา
เช่น

s = "Test String";
cout << s.length() << endl;

จะได้ผลลัพท์คือ 11

string::max_size()

จะ return ค่าความยาวของข้อความทั้งหมดที่ string จะสามารถเก็บได้

string::resize(size_t n)
string::resize(size_t n, char c)

จะเป็นการเปลี่ยนขนาดของ string และถ้าเป็นการเพิ่มขนาด จะเอา c ไปต่อท้าย
แต่ถ้าไม่ได้ใส่ค่า c ค่า default คือ '\0'

s = "Test String";
s.resize(7);      // s = "Test St"
s.resize(9, '_'); // s = "Test St__"
s.resize(12);     // s = "Test St__"


string::clear()


เป็นการลบค่าใน string ออก


string::empty()


เป็นการตรวจสอบว่า string มีข้อมูลหรือไม่


string::at(size_t pos)
string::operator[]


คือ char ตัวที่ pos ของ string เช่น s[2]


string::operator+=


เป็นการต่อ string เช่น


s = "String1";
s += " String2";
// s = "String1 String2";


มีความหมายเหมือนกับ


s = s + " String2";


เป็นยังไงกันบ้างครับ string ใช้ง่ายใช่ไหมหล่ะ


เรามาต่อเรื่อง class กันดีกว่า


คราวนี้ผมจะพูดเรื่องการนำฟังก์ชันใน class ออกมาเขียนข้างนอก
จำได้ไหมครับ ว่า class เขียนยังไง ?
คราวนี้ผมจะเขียนแต่ prototype ของฟังก์ชัน


class triangle {
    private:
        float b, h;
    public:
        void setBase(float);
        void setHight(float);
        float getArea();
};


ผมจะนิยามฟังก์ชันข้างนอก ต้องใช้ เครื่องหมาย scope (::) ขั่นระหว่างชื่อ class กับชื่อฟังก์ชัน



void triangle::setBase(float base)
{
    b = base;
}

void triangle::setHight(float hight)
{
    h = hight;
}

float triangle::getArea()
{
    return 0.5 * b * h;
}

ทำไมถึงต้องทำแบบนี้ ?
เพราะว่าถ้าในฟังก์ชันมีคำสั่งเยอะมาก จะทำให้เรามองภาพรวมของ class ยาก
ถ้าใน class มีแต่ prototype และตัวแปร เราจะมองเห็นภาพรวมง่ายขึ้น



หวังว่าบทความนี้จะมีประโยชน์สำหรับใครหลาย ๆ คน นะครับ