2011/11/16

.NET Framework - #2 Windows Application


สวัสดีครับ เป็นยังไงกันบ้างครับ
วันนี้เราจะมาสร้าง Form ใน Windows กันครับ

เหมือนเดิมนะครับ ให้สร้าง Project เปล่า ๆ ขึ้นมา แล้วก็เพิ่ม References 3 ตัวคือ System, System.Drawing และ System.Windows.Forms

สำหรับ C++/CLI ให้เพิ่มตรง Project Properties นะครับ


F#, C#, VB.NET ก็เพิ่มตรง References ได้เลยครับ



แล้วก็ไปตั้งค่าอีกนิดนึงครับ
C#, VB.NET, F# ให้เข้าไปที่ Project Properties แล้วตั้ง Output type เป็น Windows Application



ส่วน C++/CLI ให้เข้าไปที่ Project Properties, ในส่วนของ Linker ตรง System เปลี่ยน SubSystem เป็น Windows และตรง Advanced เปลี่ยน Entry Point เป็น main




ตั้งค่าเสร็จแล้ว ก็มาเขียนโค้ดกันเลยครับ~~~~!!!


C++/CLI

using namespace System;
using namespace System::Drawing;
using namespace System::Windows::Forms;

[STAThread]
int main()
{
    Form ^f = gcnew Form();
    f->Text = "C++/CLI Form";
    Application::Run(f);
    return 0;
}


C#

using System;
using System.Drawing;
using System.Windows.Forms;

class Program
{
    [STAThread]
    static void Main()
    {
        Form f = new Form();
        f.Text = "C# Form";
        Application.Run(f);
    }
}


VB.NET

Option Strict On
Option Explicit On

Imports System
Imports System.Drawing
Imports System.Windows.Forms

Module Program
    <STAThread>
    Sub Main()
        Dim f As New Form()
        f.Text = "VB.NET Form"
        Application.Run(f)
    End Sub
End Module


F#

open System
open System.Drawing
open System.Windows.Forms

[<STAThread>]
let f = new Form(Text = "F# Form")
Application.Run(f)



เป็นยังไงกันบ้างครับ เห็นไหมครับว่าภาษา .NET เหมือนกันโค้ดแทบไม่ต่างกันเลย ต่างกันแค่ไวยากรณ์ของภาษานั้น ๆ

วันนี้ก็เอาไว้เท่านี้นะครับ ขอให้สนุกกับการเขียนโปรแกรมครับผม ^w^

(โปรแกรมที่ผมใช้วันนี้คือ Visual Studio 11 Developer Preview นะครับ)

2011/11/11

F# - #3

สวัสดีครับ วันนี้เราก็มาฝึกเขียนภาษา F# กันเหมือนเดิมนะครับ
ก่อนอื่นผมจะขอพูดเกี่ยวกับฟังก์ชันอีกหน่อยนะครับ
คราวนี้ให้เปิดตัว F# Interactive (Console) นะครับ



แล้วลองพิมพ์ลงไปว่า

let f a b = a + b;;
let g(a, b) = a + b;;

จะเห็นว่า f กับ g จะไม่เหมือนกัน
ลองมาดูที่ฟังก์ชัน f กันก่อน

val f : int -> int -> int

หมายถึง f จะรับค่า int 2 ตัว แล้วส่งค่า int กลับมา
ส่วน g

val g : int * int -> int

หมายถึง g จะรับค่า int * int ที่เป็น tuple แล้วจะส่งค่า int กลับออกมา



คราวนี้เราลองมากำหนดชนิดของค่าที่รับเข้าไปกัน

let f (a : float) (b : float) = a + b;;

val f : float -> float -> float

จะเห็นว่าผลลัพท์ (ค่าที่ฟังก์ชันส่งกลับมา) จะเปลี่ยนด้วย

คราวนี้เรากลับมาที่ Visual Studio กันนะครับ
วันนี้เราจะมาดูวิธีเขียนเงื่อนไขกัน

let a = 10
if a < 20 then
    printfn "a < 20"
else
    printfn "a >= 20"

วิธีเขียนจะคล้าย ๆ Object Pascal กับ VB.NET

ส่วนเครื่องหมายจะมี
= เท่ากับ
< น้อยกว่า
> มากกว่า
<> ไม่เท่ากับ

แต่ถ้ามีหลายเงื่อนไข จะใช้ && (and) กับ || (or) เป็นตัวเชื่อม และ elif จะหมายถึง else if

let a = 10
if a < 20 && a >= 0 then
    printfn "0 <= a < 20"
elif a >= 20 then
    printfn "a >= 20"
else
    printfn "a < 0"

คราวนี้มาดูวิธีตรวจสอบค่ากันบ้าง ที่ในภาษา C/C++, C# เป็น switch case แต่ใน F# จะใช้ match with

let a = 4
match a with
| 0 -> printfn "Zero"
| 1 -> printfn "One"
| 2 | 3 -> printfn "2 or 3"
| x when a > 3 -> printfn "%i" x
| _ when a < -4 -> printfn "< -4"
| _ -> printfn "Other"

เครื่องหมาย | (pipe) จะเหมือนกับ case ในภาษา C#
| x when a > 3 หมายถึง ให้ค่าเป็น x ถ้า a > 3 หรือจะเขียนเป็น | x when x > 3 ก็ได้
| _ when a < -4 ไม่สามารถเขียนเป็น _ when _ < -4 ได้
นอกจากนี้ยังเขียนเป็น | x when x > 3 && x < 6 ได้อีกด้วย

ลองเขียนเคสอื่น ๆ ดูนะครับ

คราวนี้ลองมาดู resursive function (ฟังก์ชันเรียกตัวเอง) กันบ้าง

let rec fac n =
    match n with
    | _ when n < 0 -> failwith "n must >= 0"
    | 0 | 1 -> 1
    | _ -> n * fac(n - 1)

เราจะใช้ rec ต่อหลัง let เพื่อบอกว่า ฟังก์ชันที่จะสร้างเป็นฟังก์ชันแบบ recursive ครับ
ส่วน failwith หมายถึง ให้แสดง error ครับ ลองใส่ค่าติดลบดูก็ได้ครับ
ส่วนที่ต้องใส่วงเล็บ ตรง fac(n - 1) ก็เพราะว่า ถ้าเราเขียนเป็น n * fac n - 1 มันจะกลายเป็น n * fac(n) - 1

คราวนี้เราลองมารับค่ากันบ้างครับ
ก่อนอื่นเราต้องเรียก namespace System ขึ้นมาก่อน ด้วยคำสั่ง open เหมือนกับ using ใน C# และ Import ใน VB.NET

open System

printf "Enter a number: "
let a = int(Console.ReadLine())
printfn "%i" a

คราวนี้ถ้าจะรับข้อความเข้ามาทั้งบรรทัด

open System

printf "Enter a string: "
let a = Console.ReadLine()
printfn "%s" a

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

open System

printf "Enter a string: "
let a = Console.ReadLine().Split()
printfn "%A" a

ตอนนี้เราจะได้ a เป็น array นะครับ จึงไม่สามารถใช้ %s กับ a ได้
จากตรงนี้ลองพิมพ์ข้อความลงไปว่า Hello World
เราจะได้ [|"Hello"; "World"|]
ซึ่งเราจะเขียนแบบนี้ตอนสร้าง array ครับ

let a = [|1; 2; 3; 4|]
printfn "%A" a

สมาชิกแต่ละตัวจะใช้ ; (semi-colon) เป็นคั่น และใช้ [|   |] ครอบ

แล้วถ้าต้องการรับค่าเข้ามาแล้วแปลงเป็น int หล่ะจะทำยังไง
เช่น ใส่ค่าเข้ามาว่า 1 6 12 จะให้รับเข้ามาเป็น array [|1; 6; 12|]

open System

printf "Enter a string: "
let a = Array.map(fun x -> int x) (Console.ReadLine().Split())
printfn "%A" a

เราจะใช้คำสั่ง Array.map เข้ามาช่วย แล้วเขียนฟังก์ชันข้างใน
หรือจะเขียนว่า

let a = Console.ReadLine().Split() |> Array.map(fun x -> int x)

ก็ได้

แล้วเจ้า |> (pipe + >) มันคืออะไร ?

เครื่องหมาย |> นิยามโดย

let (|>) x f = f x

ลองดูกับฟังก์ชันง่าย ๆ

open System
let a = Math.Cos 5.0
printfn "%f" a

เราจะเขียนเป็น

let a = 5.0 |> Math.Cos

ก็ได้ มีความหมายเหมือนกัน

เริ่มงงกันแล้วใช่ไหมครับ งั้นวันนี้พอแค่นี้ก่อนละกันครับ เดี๋ยวผมจะมาพูดเรื่อง Array อีกทีนะครับ

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