Erlang Complex Data Structures

ในเอิร์ลแลง(Erlang)โครงสร้างข้อมูลที่ซับซ้อนหมายถึงการนำโครงส้างข้อมูลแบบพื้นฐาน ไม่ว่าจะเป็นอะตอม ลิสท์ ทัปเปิล และอื่นๆมาประกอบรวมกันเพื่อจำลองข้อมูลที่ซับซ้อนบางอย่าง เช่นเราต้องการสร้าง
person ให้เป็นโครงสร้างที่ซับซ้อนที่ประกอบไปด้วย ชื่อ นามสกุล สัตว์เลี้ยง ความชื่นชอบ หรือ อื่นๆ จะได้ออกมาประมาณนี้
[{person,"Joe","Armstrong",
    [ {shoeSize,42},
        {pets,[{cat,zorro},{cat,daisy}]},
        {children,[{thomas,21},{claire,17}]}]},
 {person,"Mike","Williams",
    [ {shoeSize,41},
        {likes,[boats,wine]}]}
]

หรือถ้าเราต้องการสร้าง person ขึ้นมาแบบค่อยเป็นค่อยไปทีละขั้น ด้วยการใช้โครงสร้างพื้นฐานก็ทำได้แต่ผลที่ออกมาจะดูอ่านยากมาก

1> JoeAttributeList = [{shoeSize,42}, {pets,[{cat, zorro},{cat,daisy}]},
1> {children,[{thomas,21},{claire,17}]}].
        [{shoeSize,42},
            {pets,[{cat,zorro},{cat,daisy}]},
            {children,[{thomas,21},{claire,17}]}]
2> JoeTuple = {person,"Joe","Armstrong",JoeAttributeList}.
        {person,"Joe","Armstrong",
            [{shoeSize,42},
                {pets,[{cat,zorro},{cat,daisy}]},
                {children,[{thomas,21},{claire,17}]}]}
3> MikeAttributeList = [{shoeSize,41},{likes,[boats,wine]}].
        [{shoeSize,41},{likes,[boats,wine]}]
4> MikeTuple = {person,"Mike","Williams",MikeAttributeList}.
        {person,"Mike","Williams",
            [{shoeSize,41},{likes,[boats,wine]}]}
5> People = [JoeTuple,MikeTuple].
        [{person,"Joe","Armstrong",
            [{shoeSize,42},
                {pets,[{cat,zorro},{cat,daisy}]},
                {children,[{thomas,21},{claire,17}]}]},
         {person,"Mike","Williams",
            [{shoeSize,41},{likes,[boats,wine]}]}]

จ้อได้เปรียบอีกข้อของเอิร์ลแลงคือเราไม่ต้องนั่งเสียเวลาจัดการกับเมมโมรี่ เองเหมือนกับภาษาซี กระบวนการจัดการเมมดมรี่จะถูกควบคุมโดยกาเบจคอลเลคชั่น คือวีเอ็มจะจัดการคืนเมมโมรี่เมื่อไม่มีการใช้งานเมมโมรี่ส่วนที่ถูกจองไว้ ตามระยะเวลาที่กำหนด

Erlang Pattern Matching
การเปรียบเทียบรูปแบบ(Pattern Matching)ในเอิร์ลแลงใช้สำหรับงานเช่น
• การกำหนดค่าให้ตัวแปร
• การควบคุมการทำงานของโปรแกรม
• การดึงค่าออกมาจากข้อมูลที่ถูกประกอบกันขึ้นมา(compound)

การเปรียบเทียบรูปแบบสามารถเขียนได้ในรูปนี้

    รูปแบบ(Pattern) = นิพจน์(Expression)

ตัว รูปแบบ(Pattern)นั้นจะประกอบไปด้วยตัวแปรที่ถูกผูก(bound)และตัวแปรที่ยัง ไม่ถูกผูก(unbound) รวมทั้งประเภทข้อมูลพื้นฐานต่างๆเช่น อะตอม อินทิเจอร์ และ สตริง 

    Double
    {Double, 34}
    {Double, Double}
    [true, Double, 23, {34, Treble}]

นิพจน์(Expression)ประกอบไปด้วยประเภทของข้อมูลต่างๆ, ตัวแปรที่ถูกผูกแล้ว, ตัวดำเนินการทางคณิตศาสตร์, การเรียกฟังก์ชั่น (ไม่สามารถใช้ ตัวแปรที่ยังไม่ถูกผูก ได้) เมื่อเราเห็นภาพแล้วว่าสิ่งที่อยู่ทั้งสองด้านของการทำการเปรียบเทียบรูปแบบ เราก็ควรจะรู้ว่าอะไรจะเกิดขึ้นเมื่อตัวเปรียบเทียบรูปแบบเริ่มทำงาน ผลของการทำงานมีสองแบบคือ

• การเปรียบเทียบสำเร็จ ส่งผลให้เราสามารถผูกค่าเข้ากับตัวแปรได้ และส่งค่านั้นกลับไป
• การเปรียบเทียบล้มเหลว ไม่มีก่ารผูกค่าเข้ากับตัวแปรใดๆเลย

แล้วเราจะรู้ได้อย่างไรว่าการเปรียบเทียบของเราสำเร็จหรือไม่? ก่อนอื่นเราต้องเข้าใจกระบวนการทำงานก่อน โดยที่การทำงานจะเริมจากการตรวจสอบนิพจน์ที่อยู่ทางขวามือก่อนที่จะทำการ เปรียบเทียบค่าของมันกับรูปแบบ(Pattern)ทางซ้ายมือ โดยจะมีกฎการเปรียบเทียบอยู่สี่ข้อคืด

• ทั้ง นิพจน์และตัวรูปแบบจะต้องมีลักษณะเหมือนกันเช่นทัปเปิลจะต้องมีจำนวนอิลิเมน ท์เท่ากันเท่านั้น ลิสท์ที่มีเทอมเป็น [X|Xs] จะต้องถูกเทียบกับลิสท์ที่ไม่เป็นลิสท์ว่างเท่านั้น 
• The literals in the pattern have to be equal to the values in the corresponding place in the value of the expression. 
• ตัวแปรที่ยังไม่ถูกผูกจะโดนผูกเข้ากับค่า ก็ต่อเมื่อกระบวนการเปรียบเทียบรูปแบบทำได้สำเร็จ
• ตัวแปรที่ถูกผูกแล้วจะต้องมีค่าเหมือนกับที่ที่มันผูกไว้ของนิพจน์ทางด้านขวา

ตัวอย่าง, ลองเขียน Sum = 1+2 โดยที่ตัวแปรที่ยังไม่ถูกผูกอย่าง Sum จะถูกใช้เพื่อผูกเข้ากับผลของการบวก 1 กับ 2 กระบวนการคือเอิร์ลแลงจะบวก 1 กับ 2 ก่อนแล้วหลังจากนั้นจะไปตรวจดู Sum ว่าเป็นตัวแปรแบบที่ยังไม่ถูกผูกหรือไม่ถ้าใช่มันจะใส่ค่า 3 ให้กับ Sum เพราะเงือนไขการเปรียบเทียบรูปแบบ ถูกต้อง ในทางกลับกันถ้า Sum ถูกผูกแล้ว Sum จะไม่ถูกกำหนดค่าใหม่เพราะผลการเปรียบเทียบล้มเหลว กรณีเดียวที่การเปรียบเทียบจะสำเร็จโดยที่ Sum ถูกผูกแล้วก็คือ Sum จะต้องมีค่าเป็น 3 มาก่อนแล้วเท่านั้น
อีกตัวอย่าง

1> List = [1,2,3,4].
[1,2,3,4]

กรณีนี้การเปรียบเทียบจะสำเร็จ List จะมีค่าเป็น [1,2,3,4] 
ตัวอย่างต่อไป:

2> [Head|Tail] = List.
[1,2,3,4]
3> Head.
1
4> Tail.
[2,3,4]
กรณีนี้ก็สำเร็จเช่นกันเพราะไม่มีการเปรียบเทียบกับ ลิสท์ว่าง 
ตัวอย่างต่อไป

5> [Head|Tail] = [1].
** exception error: no match of right hand side value [1]
6> [Head|Tail] = [1,2,3,4].
[1,2,3,4]
7> [Head1|Tail1] = [1].
[1]
8> Tail1.
[]

เกิดอะไรขึ้นกับคำสั่งที่ 5 ? มันเหมือนจะไม่มีปัญหาอะไร แต่!!! [Head|Tail] ถูกผูกเข้ากับ [1,2,3,4] เรียบร้อยแล้วดังนั้นเมื่อเราพยายามจะถูกมันเข้ากับ [1] มันจะเอา [1] ไปเทียบกับ [1,2,3,4] และแน่นอนว่ามันไม่เท่ากันทำให้การเปรยบเทียบล้มเหลว แต่ถ้าเราใช้คำสั่งที่ 6 การเปรียบเทียบจะสำเร็จ ดังนั้นถ้าเราต้องการดึงเอาค่าออกมาจากลิสท์ [1] เราจำเป็นต้องใช้ลิสท์อีกตัวที่ยังไม่ถูกผูกค่าไว้

9> {Element, Element, X} = {1,1,2}.
{1,1,2}
10> {Element, Element, X} = {1,2,3}.
** exception error: no match of right hand side value {1,2,3}

เกิด อะไรถ้าตัวแปรที่เราใช้ชื่อซ้ำกันตามตัวอย่างที่ 9 ตัวแปรตัวแรกจะไม่ถูกผูกโดยทันทีแต่มันจะรอ ส่วนอิลิเมนท์ที่สองจะถูกผูกและจะสำเร็จเมื่อค่าที่ถูกเปรียบเทียบมีค่าเป็น 1 เท่านั้น โดยให้ดูคำสั่งที่ 10 ในกรณีที่การเปรียบเทียบไม่สำเร็จเพราะค่าไม่สอดคล้องกัน

11> {Element, Element, _} = {1,1,2}.
{1,1,2}

ต่อ ไปคือเรื่องสัญลักษณ์แบบเปิด(wildcard symbol), _ , ผลของมันคือมันจะถูกผูกเข้ากับอะไรก็ตามที่ยังไม่ถูกผูก ดังตัวอย่าง (นิยมใช้ในการดึงข้อมูลออกมาจากลิสท์ที่มีขนาดใหญ่มากและเราต้องการดึงบางอิ ลิเมนท์ออกมา)

12> {person, Name, Surname} = {person, "Jan-Henry", "Nystrom"}.
{person,"Jan-Henry","Nystrom"}
13> [1,2,3] = [1,2,3,4].
** exception error: no match of right hand side value [1,2,3,4]

วุ่นวาย ไหมครับ แล้วทำไมเราต้องใช้การเปรียบเทียบรูปแบบ? อันดับแรกคือเอาไว้กำหนดค่าให้ตัวแปร ในเอิร์ลแลงถ้าเราทำ Int = 1 การทำงานคือมันจะเปรียบเทียบค่าที่อยู่ในตัวแปร Int กันอินทิเจอร์ 1 ในกรณีที่ Int ยังไม่ถูกผูกมันจะถูกผูกเข้ากับค่าอะไรก็ตามที่อยู่ทางขวามือ นี่เป็นกระบวนการการกำหนดค่าให้ตัวแปรซึ่งจริงมันไม่ได้กำหนดค่าตรงๆแต่มัน จะทำการเปรียบเทียบรูปแบบตัวแปรนั่นเองนั่นเอง  ต่อไปให้เราเขียน Int = 1 และตามด้วย  Int = 1+0 ขั้นแรกทำการผูก Int เข้ากับ 1 หลังจากนั้นจะทำการบวก 0 เพิ่มเข้าไปกับ 1 แล้วทำการเปรียบเทียบค่าที่ได้กับค่าที่ผูกอยู่กับ Int ซึ่งแน่นอนมันจะเท่ากันทำให้ผลของการทำการเปรียบเทียบรูปแบบถูกต้อง ในทางกลับกันถ้าเราเปลี่ยนคำสั่งที่สองเป็น Int = Int +1 ผลที่ได้คือการเปรียบเทียบจะล้มเหลวเนื่องจาก 2 จะไม่เท่ากับค่าที่ผูกอยู่กับ Int ที่มีค่าเป็น 1

การเปรียบเทียบรูปแบบ ยังถูกนำไปใช้ในการควบคุมการทำงานของโปรแกรมได้อีกด้วย ซึ่งจะขอกล่าวถึงเรื่องนี้ในภายหลัง ดังนั้นเราควรมาทดสอบความรู้เรื่องการเปรียบเทียบรูปแบบกันเสียหน่อย

{A, A, B} = {abc, def, 123}

การเปรียบเทียบแบบแรกเราจะพิจรณาก่อนว่าทัปเปิลทั้งสองมีขนาดเท่ากันหรือไม่ ในที่นี้มันมีขนาดเป็นสามเท่ากันดังนั้นขั้นแรกสำเร็จ ต่อไปคือการเปรียบเทียบในระดับอิลิเมนท์ โดยที่ A = abc ก่อนแล้ว A ตัวที่สองจะถูกเปรียบเทียบกับ def ซึ่งจริงๆแลอ้วค่าเริ่มต้านของ A คือ abc ดังนั้นเมื่อเราพยายามเทียบกับ def ผลที่ได้จึงล้มเหลว
การเปรียบเทียบรูปแบบ [A,B,C,D] = [1,2,3] จะล้มเหลวถึงแม้ว่าทั้งสองฟากจะเป็นลิสท์เหมือนกันแต่จำนวนอิลิเมนท์ของทั้ง สองฝั่งนั้นไม่เท่ากันเพราะทางซ้ายมีสี่ตัวแต่ทางขวามีสามตัว แต่บางคนอาจจะสงสัยว่า แล้ว D ไม่ใช่ลิสท์ว่างหรือ? ความจริงคือเนื่องจากเครื่องหมายที่เราใช้แบ่งระหว่างอิลิเมนท์ C กับ D คือ , ไม่ใช่เครื่องหมาย cons ทำให้ D ไม่สามารถเป็นลิสท์ว่างได้ แต่ถ้าเราเขียนใหม่เป็น [A,B, C|D] = [1,2,3] การเปรียบเทียบรูปแบบจะสำเร็จ โดยที่ A,B,C จะมีค่าเป็น 1,2,3 ส่วน D จะถูกผูกเข้ากับลิสท์ว่างอัตโนมัติ เรามาลองอีกตัวอย่าง [A, B|C] = [1,2,3,4,5,6,7] ผลที่ได้คือ A กับ B จะมีค่าเป็น 1 และ 2 ตามลำดับส่วน C จะถูกผูกเข้ากับ [3,4,5,6,7] กรณีที่เราเขียน [H|T] = [] ผลที่ได้คือล้มเหลวเพราะเราไม่รู้จะเปรียบเทียบ H กับอะไรเนื่องจากอีกด้านเป็นลิสท์ว่าง สุดท้ายเรามาลองดึงเอาค่าออกมาจากข้อมูลแบบประกอบ(compound data types)

{A, _, [B|_], {B}} = {abc, 23, [22, 23], {22}}

ผลการเปรียบเทียบคือสำเร็จ A จะถูกผูกเข้ากับอะตอม abc ส่วน B จะถูกผูกเข้ากับอินทิเจอร์ 22

14> Var = {person, "Francesco", "Cesarini"}.
{person, "Francesco", "Cesarini"}
15 {person, Name, Surname} = Var.
{person, "Francesco", "Cesarini"}

เราตั้งใจจะดึงเอาค่าต่างๆในทัปเปิลที่ใช้ชื่อแทคว่า person ออกมาเก็บไว้ในทัปเปิลอีกตัวซึ่งผลที่ได้คือ Name จะได้ค่า "Francesco" ส่วน Surname จะได้ค่า "Cesarini" ในเรื่องการดึงค่าออกมาจากลิสท์หรือทัปเปิลนั้นที่นิพจน์ที่อยู่ทางซ้ายมือ ตัวแปรต่างๆสามารถขึ้นต้นได้ด้วย _ ซึ่งจะหมายถึง "ไม่สนใจ" เครื่องหมายนี้มักถูกใช้กับค่าที่เราไม่สนใจแต่ตัวมันเองมีพฤติกรรมเหมือน กับตัวแปรทั่วๆไปเช่นเราสามารถนำมันมาเปรียบเทียบ ตรวจสอบ และนำไปใช้งานได้ การใช้ตัวแปรแบบ "ไม่สนใจ" นี้ถือว่าเป็นข้อปฎิบัติที่ดีของการเขียนโปรแกรมบนเอิร์ลแลง เนื่องจากคนที่มาอ่านโปรแกรมต่อจากเราจะได้แยกแยะได้ว่าบริเวณไหนที่เขาไม่ ต้องสนใจ ยกตัวอย่างเช่น

{A, _, [B|_], {B}} = {abc, 23, [22, 24], {22}}

จะเห็นว่า _ จะไม่ถูกผูกเข้ากับค่าอะไรเลยและมันก็ไม่สนใจด้วยว่าค่าอะไรที่เรากำลัง เปรียบเทียบอยู่ แต่ในทางกลับกันถ้าเราเขียนอีกแบบ

{A, _int, [B|_int], {B}} = {abc, 23, [22, 24], {22}}

ความหมายของมันจะแตกต่างออกไปอย่างสิ้นเชิงโดยที่ _int จะถูกผูกเข้ากับ 23 และหลังจากนั้นเมื่อมันเลื่อนไปเปรียบเทียบกับอิลิเมนท์ที่สองของลิสท์ที่มี ค่าเป็น 23 ซึ่งจะส่งผลให้การเปรียบเทียบล้มเหลว ปกติแล้วการใช้งานตัวแปรที่ขึ้นต้อนด้วยเครื่องหมาย _ เช่น _int นั้นทำให้โค้ดของเราอ่านได้ง่ายขึ้นแต่ผลที่ได้กลับมาคือบางครั้งเราลืมไป ว่าตัวแปรของเราถุกกำหนดค่าได้เพียงครั้งเดียวเท่านั้นและอาจส่งผลให้ โปรแกรมของเราเกิดปัญหาได้มากขึ้นด้วยเช่นกัน ดังนั้นการใช้ _ เราควรใช้งานอย่างระมัดระวัง


edit @ 15 Dec 2009 11:02:03 by cyber-climber

edit @ 15 Dec 2009 11:05:36 by cyber-climber

Erlang Term Comparison
การเปรียบเทียบเทิร์มในเอิร์ลแลงนั้นจะต้องใช้นิพจน์สองตัวโดยจะต้องใส่ไว้ทั้งสองด้านของตัวดำเนินการเปรียบเทียบผลที่ได้จาการเปรียบเทียบคืออะตอมที่เป็นจริงหรือเท็จ โดยที่ตัวดำเนินการ เท่ากับ(==) และ ไม่เท่ากับ(/=) จะทำการเปรียบเทียบค่าของนิพจน์ที่อยู่ทั้งสองข้างโดยไม่สนใจประเภทของนิพจน์นั้น เช่น 1==one ผลเป็นเท็จ, one = one ผลที่ได้คือจริงต่อไป 1 == 1.0 ผลเป็นจริง, 1 /= 1.0 ผลเป็นเท็จเพราะทั้งสองแบบนี้จะมีการแปลงค่าของนิพจน์ก่อนทำการเปรียบเทียบแต่ในเอิร์ลแลงยังมีตัวกำเนินการเปรีบยเทียบอีกสองตัวที่น่าสนใจคือ เท่ากันจริง(=:=) ไม่เท่ากันจริง(=/=)  ตัวดำเนินการประเภทนี้จะทำการเปรียบเทียบทั้งค่าและประเภทไปด้วยกันดังนั้นถ้าเราทำแบบเดิมแต่เปลี่ยนตัวดำเนินการ 1 =:= 1.0 และ 1 =/= 1 ผลจะเป็นเท็จทั้งคุ่แต่ 1 =/= 1.0 จะเป็นจริงและนอกจากเราจะเปรียบเทียบการเท่ากันแล้วเรายังเปรียบเทียบเชิงลำดับได้อีกเช่น มากกว่า(>) น้อยกว่า(<) มากกว่าหรือเท่ากับ(>=) น้อยกว่าหรือเท่ากับ(<=)
สรุปเครื่องหมาย
== Equal to
/= Not equal to
=:= Exactly equal to
=/= Exactly not equal to
=< Less than or equal to
< Less than
>= Greater than or equal to
> Greater than
สำหรับการเปรียบเทียบนิพจน์ในเอิร์ลแลงนั้นมีลำดับขั้นในการพิจรณาดังนี้(ในกรณีที่นิพจน์ทั้งสองเป็นประเภทที่แตกต่างกัน)

number < atom < reference < fun < port < pid < tuple < list < binary

จากหลักการเปรียบเทียบข้างบนจะเห็นได้ว่าตัวเลขจะเล็กกว่าอะตอม และทัปเปิลจะเล็กว่าลิสท์

3> 11
true
4> {123,345}<[].
true

การเปรียบเทียบลิสท์จะใช้วิธีการเปรียบเทียบไปทีละอิลิเมนท์ เปรียบเทียบไปเรื่อยๆจนกว่าด้านใดด้านหนึ่งจะหมดก็ถือว่าด้านนั้นน้อยกว่า
5> [boo,hoo]<[adder,zebra,bee].
false
6> [boo,hoo]<[boo,hoo,adder,zebra,bee].
true
ในทางกลับกันสำหรับทัปเปิลนั้นจะใช้วิธีการนับจำนวนสมาชิกของแต่ละทัปเปิลก่อนแล้วตามมาด้วยค่าของสมาชิกแต่ละตัว
7> {boo,hoo}<{adder,zebra,bee}.
true
8> {boo,hoo}<{boo,hoo,adder,zebra,bee}.
true

และด้วยความสามารถในการเปรียบเทียบค่าของข้อมูลหลายๆประเภททำให้เราสามารถเขียนฟังก์ชั่นเช่นฟังก์ชั่นสำหรับการเรียงลำดับสมาชิกของลิสท์ที่สมาชิกแต่ละตัวมีประเภทที่แตกต่างกันได้โดยไม่ต้องกังวลเรื่องของการแปลงค่าต่างๆเหล่านั้นเลยอย่างไรก็ตามการใช้ตัวดำเนินการ เท่ากันจริง และ ไม่เท่ากันจริง นั้นจำเป็นต้องเตรียมข้อมูลเพิ่มเติมให้กับคอมไพล์เลอร์และเครื่องมือสำหรับจัดการกับไทป์ ทำให้เราต้องเขียนโค้ดอย่างระมัดระวังขื้น  นอกจากนี้ในบางกรณีโค้ดเราจะดูน่าเกลียดอย่างมากทำให้ในทางปฎิบัติแล้วเราควรจะใช้ตัวดำเนินการเท่ากับและไม่เท่ากับเท่านั้น จากนั้นเรามาลองเปิดเอิร์ลแลงเชลขึ้นมาเพื่อทดสอบตัวดำเนินการเปรียบเทียบดูว่าจะเป็นอย่างไร

1> 1.0 == 1.
true
2> 1.0 =:= 1.
false
3> {1,2} < [1,2].
true
4> 1 =< 1.2.
true
5> 1 =/= 1.0.
true
6> (1 < 2) < 3.
false
7> (1 > 2) == false.
true

Erlang Variables
ตัวแปรถูกใช้สำหรับเก็บค่าต่างๆ สำหรับเอิร์ลแลงแล้วตัวแปรนั้นจะขึ้นต้นด้วยอักษรตัวใหญ่ และอาจตามด้วยตัวอักษรตัวใหญ่หรือเล็ก ตัวเลข เครื่องหมาย _ แต่ไม่สามารถใช้อักขระพิเศษได้ยกตัวอย่างการประกาศตัวแปรกตามมาตรฐาน A_long_variable_name Flag Name2 DbgFlag แต่สำหรับตัวแปรในเอิร์ลแลงนั้นจะแตกต่างจากภาษาโปรแรมมิ่งที่เราคุ้นเคยกัน โดยในสโคปของฟังก์ชั่น ที่รวมไปถึงเอิร์ลแลงเชลโพรเซส นั้นเมื่อเรากำหนดค่าให้ตัวแปรแล้วเราจะไม่สามารถเปลี่ยนค่ามันได้อีก เราเรียกกระบวนการนี้ว่าการกำหนดค่าเพียงครั้งเดียว(single assignment)
ยกตัวอย่างเช่น

Double = 2,
Double = Double * Double

ผลที่ได้คือจะเกิดเออร์เร่อขณะรันไทม์เนื่องจากเราได้กำหนดค่าให้ Double เป้น 2 ไปก่อนที่จะพยายามกำหนดให้เท่ากับ Double*Double ทางแก้คือเราต้องสร้างตัวแปรตัวใหม่ขึ้นมาเพื่อรับค่า Double*Double แทนดังนี้

Double = 2,
NewDouble = Double * Double
การกำหนดค่าครั้งเดียวนั้นอาจเป็นเรื่องแปลกสำหรับคนทั่วไปในครั้งแรกๆแต่อย่างไรก็ตาม หลังจากใช้ไปสักพักก็จะเริ่มปรับตัวเข้าหาการทำงานแบบนี้ได้ ข้อดีข้อแรกของการทำแบบนี้คือมันช่วยลดข้อผิดพลาดในการเขียนโปรแกรมลงได้เยอะมาก เนื่องจากค่าของตัวแปรไม่ถูกเปลี่ยนไปเปลี่ยนมาเรื่อยๆนั่นเอง

การเรียกฟังก์ชันต่างๆในเอิร์ลแลงจะทำผ่านค่า(by value)เสมอพารามิเตอร์ทุกตัวที่ถูกส่งไปให้ฟังก์ชั่นจะถุกตรวจสอบก่อนเสมอก่อนที่ตัวฟังก์ชั่นจะทำงาน อีกข้อที่สำคัญคือตัวแปรทุกตัวในเอิร์ลแลงเป็นตัวแปรโลคอลดังนั้นตัวแปรแบบโกลบอลจะไม่มีในเอิร์ลแลง นั่นเป็นอีกข้อที่ช่วยให้เราทำงานได้ง่ายขึ้น

คุณสมบัติอีกข้อที่สำคัญคือเราไม่มีความจำเป็นต้องประกาศตัวแปรก่อนที่จะใช้งานมัน ดังนั้นนี่เป็นอีกแนวคิดที่ทำให้คนที่เคยเขียน C หรือ Java มาก่อนอาจะสับสนได้ สาเหตุที่ทำให้เอิร์ลแลงไม่มีเช่นนั้นเพราะเอิร์ลแลงเป็นภาษาไดนามิกส์ ประเภทของข้อมูลจะถูกกำหนดขณะทำงาน ดังนั้นจึงมีความเป็นไปได้ที่เราจะทำอะไรแปลกๆเช่นพยายามคูณตัวเลขกับตัวอักษร
 
Var = one,
Double = Var * 2
ดังนั้นข้อควรจำที่ควรคิดไว้เสมอคือตัวแปรถูกกำหนดค่าได้ครั้งเดียว ดังนั้นปัญหาอาจเกิดขึ้นในเอิร์ลแลงเชลได้เพราะโปรแกรมของเราอาจต้องทำงานอย่างต่อเนื่องไปเรื่อยๆเป็นปีๆและเราใช้เชลเพียงเชลเพียงเชลเดียวในการทำงานร่วใกบโปรแกรมนั้น ทำให้บางครั้งเราอาจทดลองอะไรบางอย่างขณะที่โปรแกรมก็ยังคงทำงานอยู่ ซึ่งอาจก่อให้เกิดปัญหาได้แต่ปะญหานี้สามารถแก้ไขได้ด้วยการใช้ f() เพื่อสั่งให้เชลลืมการกำหนดค่าของตัวแปรนั้นๆไปชั่วขณะเพื่อหลีกเลี่ยงปัญหาขณะที่เรากำลังทดลองอะไรบางอย่างอยู่เช่น

1> A = (1+2)*3.
9
2> A + A.
18
3> B = A + 1.
10
4> A = A + 1.
** exception error: no match of right hand side value 10
5> f(A).
ok
6> A.
** 1: variable 'A' is unbound **

edit @ 15 Dec 2009 11:06:08 by cyber-climber

เอิร์ลแลง(Erlang) ตอนที่ 5 List

posted on 09 Dec 2009 16:51 by roofimon  in Erlang

Erlang Lists

ลิสท์ในเอิร์ลแลงเป็นที่สำหรับเก็บชุดของอิลิเมนท์คล้ายๆกับทัปเปิลแต่กระบวนการทำงานกับลิสท์นั้นแตกต่างจากทัปเปิลมากๆ ก่อนอื่นเรามาเริ่มจากวิธีการสร้างลิสท์ก่อน โดยเราสามารถสร้างลิสท์ได้โดยการใช้เครื่องหมาย [...] และแต่ละอิลิเมนท์จะถูกคั่นด้วยเครื่องหมายลูกน้ำ , โดยที่อิลิเมนท์ในลิสท์ม่จำเป็นจะต้องเหมือนกัน เช่น

[january, february, march]
[123, def, abc]
[a,[b,[c,d,e],f], g]
[]
[{person, 'Joe', 'Armstrong'}, {person, 'Robert', 'Virding'},
{person, 'Mike', 'Williams'}]
[72,101,108,108,111,32,87,111,114,108,100]
[$H,$e,$l,$l,$o,$ ,$W,$o,$r,$l,$d]
"Hello World"

ต่อไปเรามาดูคุณสมบัติของลิสท์เบื้องต้น [a,[b,[c,d,e],f], g] ลิสท์ตัวนี้จะมีขนาดความยาวเท่ากับ 3 โดยที่อิลิเมนท์ตัวแรกเป็นอะตอม a ตัวที่สองเป็นลิสท์ [b, [c,d,e],f] และตัวที่สามคืออะตอม g
ลิสท์ว่างเราสามารถถูกสร้างได้ด้วย [], นอกจากนี้เรายังสร้างลิสท์ของแทกทัปเปิลได้ [{person, 'Joe', 'Armstrong'}, {person, 'Robert',
'Virding'}, {person, 'Mike', 'Williams'}]

Erlang Characters and Strings

สำหรับเอิร์ลแลงแล้วมันเองเป็นภาษาที่ไม่มีข้อมูลประเภทสตริง ตัวอักษรในเอิร์ลแลงที่ถูกนำเสนอออกมานั้นเบื่องหลังมันคือตัวเลข และการนำค่าตัวเลขที่ใช้แทนตัวอักษรใดๆสามารถทำได้ด้วยการใส่เครื่องหมาย $ ไว้ที่หน้าตัวอีกษรนั้นๆเช่น
1> $A.
65
2> $A + 32.
97
3> $a.
97
ดังนั้นเราจะพบว่าในเอิร์ลแลงจะไม่มีการใช้ข้อมูลที่เป็นประเภทสตริง เพราะจริงๆแล้วสตริงคือลิสท์
ของ ASCII ที่ถูกแสดงผลภายใต้เครื่องหมาย '...' ดังนั้นถ้าเราเขียนสตริง "Hello World" นั่นหมายความว่า
เรากำลังสร้างลิสท์ที่มีค่า [72,101,108,108,111,32,87,111,114,108,100]
4> [65,66,67].
"ABC"
5> [67,$A+32,$A+51].
"Cat"
6> [72,101,108,108,111,32,87,111,114,108,100].
"Hello World"
7> [$H,$e,$l,$l,$o,$ ,$W,$o,$r,$l,$d].
"Hello World"

Erlang Atoms and Strings
หลายคนอาจเริ่มสงสัยว่าแล้วอะตอมกับสตริงต่างกันอย่างไร อย่างแรกเลยคือข้อมูลทั้งสองอย่างถูกโพรเซสต่างกัน
สำหรับอะตอมสิ่งที่เราสามารถทำได้กับมันคือการเปรียบเทียบ ในทางกลับกันสำหรับสตริงแล้วเราสามารถทำงานกับมันได้หลาย
รูปแบบมาก เช่นสตริง "Hello World" นั้นสามารถแยกมันออกเป็นส่วน เช่น ["Hello", "World"]

อีกข้อแตกต่างระหว่างสตริงกับอะตอมคือเรื่องประสิทธิภาพการทำงาน เนื่องจากสตริงจะใช้พื้นที่ในการเก็บมากกว่าอะตอมทำให้ทุกๆการทำงานที่เกิดขึ้นกับสตริงจะกินเวลานานกว่าอะตอม ยกตัวอย่างเช่นถ้าเราต้องการเปรียบเทียบสตริงสองตัว(ลิสท์สองตัว)เราต้องเปรียบเทียบตัวอักษรครั้งละตัวไปจนหมด ในขณะที่ถ้าเราต้องการเปรียบเทียบอะตอมแล้วระบบจะทำการเปรียบเทียบอะตอมด้วยตัวบ่งชี้ภายใน(internal identifier) ด้วยคำสั่งเพียงคำสั่งเดียว

Erlang Building and Processing Lists
เราได้รู้จากหัวข้อก่อนหน้านี้แล้วว่าสิ่งที่ทำให้ลิสท์กับทัปเปิลแตกต่างกันก็คือการโพรเซสนั้นเองโดยที่ทัปเปิลนั้นเราสามารถทำได้เพียงดึงเอาอิลิเมนท์จากตำแหน่งที่เราต้องการออกมาเท่านั้น  ในขณะที่ลิสท์นั้นเราจะแบ่งข้อมูลในลิสท์ออกเป็นสองชุดคือหัวกับหาง โดยที่หัวคืออิลิเมนท์ตัวแรกในลิสท์และส่วนที่เหลือจะหลายเป็นหาง โดยที่เราสามารถแตกอิลิเมนท์ออกไปได้เรื่อยๆจนกว่าลิสท์นั้นจะว่าง ดังนั้นถ้าเรามีลิสท์ [1,2,3] เราจะได้หัวที่มีค่าเป็น 1 และหางเป็น [2,3] เมื่อเราเรียนรู้เกี่ยวกับเอิร์ลแลงเราจำเป็นต้องรู้การประกาศลิสท์แบบรีเคอร์สีฟเพราะถ้าเราไม่เข้าใจตั้งแต่แรกมันจะทำให้เรา งง เป็นอย่างมากดังนั้นให้ดูการประกาศลิสท์ทั้งหมดด้านล่าง ว่าผลที่ได้ออกมามีค่าเท่ากันหมด

[one, two, three, four]
[one, two, three, four|[]]
[one, two|[three, four]]
[one, two|[three|[four|[]]]]
[one|[two|[three|[four|[]]]]]

ข้อควรระวังคือเราต้องมีอิลิเมนท์ที่ฝั่งซ้ายมือของเครื่องหมาย cons และลิสท์ทางขวามือที่อยู่ในวงเล็บปีกแข็งเดียวกัน ด้วยการใช้
ข้อกำหนดนี้เราสามารถสร้างลิสท์ที่อยู่ในลักษณะที่ถูกต้องได้(ไม่ใช่ข้อกำหนดแต่ควรทำ)อย่างไรก็ตามลิสท์ในเอิร์ลแลงก็ไม่จำเป็นจะต้องเป็นจะต้องเป็นไปตามข้อกำหนดข้างต้นที่ อิลิเมนท์ด้านขวามือจะต้องเป็นลิสท์ก็ได้ยกตัวอย่างเช่นให้ลองพิมพ์  [[1, 2]|3] ลงไปในเชลแล้วดูผลที่ได้ก็คือลิสท์ที่เป็นแบบไม่ถูกลักษณะนั่นเอง ลิสท์ในลักษณะนี้เหมาะสำหรับงานประเภทเร่งรีบและรีบเร่งซึ่งเราจะกล่าวถึงเรื่องนี้ในภายหลัง  แต่อย่างไรก็ตามเราควรหลีกเลี่ยงการใช้ลิสท์ในลักษณะที่ผิดเนื่องจากถ้าเราใช้งานมันเยอะเข้า เราอาจจะแยกไม่ออกว่า เราตั้งใจจะใช้มันหรือมันเกิดจากความผิดพลาดของโปรแกรม เช่น ถ้าเราพิมพ์ [2|3] แทนที่ [2|[3]], โปรแกรมของเราสามารถถูกคอมไพล์ได้อย่างไม่มีปัญหาแต่อย่างไรก็ตามโปรแกรมส่วนนี้จะเกิดปัญหาในกรณีที่เราพยายามจะทำงานกับส่วนหางของลิสท์โดยที่เราคิดว่ามันเป็นลิสท์อย่างที่มันควรจะเป็นโดยที่แท้จริงแล้วมันเป็นอะตอม

Erlang List Functions and Operations
ลิสท์เป็นประเภทของข้อมูลที่มีประโยชน์มากที่สุดของเอิร์ลแลงเลยก็ว่าได้ และเมื่อนำมาใช้งานร่วมกับทัปเปิลทำให้มีประสิทธิภาพสูงขึ้นไปอีก เนื่องจากเราสามารถใช้แทน ข้อมูลที่มีโครงสร้างซับซ้อนได้ทั้งหมด เช่นเรามักจะใช้ลิสท์เก็บกลุ่มของออบเจคที่สามารถถูกแยกไปเป็นกลุ่มย่อยๆ เพื่อนำไปรวมกันใหม่เพื่อทำการวิเราะห์ที่เราต้องการได้

ลิสท์เองก็เตรียมโอเปอร์เรชั่นหลายๆอย่างมาให้เราใช้งานได้เลยดังตัวอย่าง โดยที่โอเปอร์เรชั่นเหล่านี้ไม่ใช้ BIFs ดังนั้นการเรียกใช้งานจำเป็นต้องใช้เครื่องหมาย : คั่น
1> lists:max([1,2,3]).
3
2> lists:reverse([1,2,3]).
[3,2,1]
3> lists:sort([2,1,3]).
[1,2,3]
4> lists:split(2,[3,4,10,7,9]).
{[3,4],[10,7,9]}
5> lists:sum([3,4,10,7,9]).
33
6> lists:zip([1,2,3],[5,6,7]).
[{1,5},{2,6},{3,7}]
7> lists:delete(2,[1,2,3,2,4,2]).
[1,3,2,4,2]
8> lists:last([1,2,3]).
3
9> lists:member(5,[1,24]).
false
10> lists:member(24,[1,24]).
true
11> lists:nth(2,[3,4,10,7,9]).
4
12> lists:length([1,2,3]).
** exception error: undefined function lists:length/1
13> length([1,2,3]).
3
แต่อย่างที่บอกว่าโอเปอร์เรชั่นเหล่านี้ไม่ใช่ BIFs ยกเว้น length
เครื่องหมาย ++ และ--, มีไว้สำหรับรวมลิสท์และแตกลิสท์ออกดังตัวอย่าง
1> [monday, tuesday, Wednesday].
[monday,tuesday,wednesday]
2>
2> [1|[2|[3|[]]]].
[1,2,3]
3> [a, mixed, "list", {with, 4}, 'data types'].
[a,mixed,"list",{with,4},'data types']
4> [1,2,3] ++ [4,5,6].
[1,2,3,4,5,6]
5> [1,2,2,3,4,4] -- [2,4].
[1,2,3,4]
6> "A long string I have split "
6> "across several lines.".
"A long string I have split across several lines."
เครื่องหมาย ++ มีไว้เพื่อรวมลิสท์สองตัวเข้าด้วยกันเป็นลิสท์ตัวใหม่เช่น [1,2]++[3,4] จะได้ [1,2,3,4]
ส่วนเครื่องหมาย -- มีไว่สำหรับแยกอิลิเมนท์ที่เรากำหนดไว้ที่ด้านขวามือ ออกมาจากลิสท์ทางซ้ายมือ
ดังนั้น [1,1] -- [1] จะได้[1], ส่วน[1,2,3,4] -- [1,4] จะได้[2,3]. แต่ถ้าเราใช้ [1,2] -- [1,1,3], ผลจะออกมาเป็น [2]. ถ้าอิลิเมนท์ทางขวามือไม่มีในด้านซ้ายมันจะถูกมองข้ามไป
ทั้ง ++ และ-- จะทำงานแบบอิงด้านขวาเป็นหลัก(right-associative),

7> [1,2,3]--[1,3]--[1,2].
[1,2]
8> ([1,2,3]--[1,3])--[1,2].
[]

สุดท้ายถ้าเราพิมพ์ "Hello " "Concurrent " "World" เราจะได้ "HelloConcurrentWorld".
อย่างไรก็ตามเราสามารถเพิ่มอิลิเมนท์เข้าไปในลิสท์ได้สองวิธีคือ
• ใช้ cons ตรงๆ [1|[2,3,4]].
• หรือใช้ ++ แทน [1] ++ [2,3,4].
การทำงานทั้งสองแบบให้ผลเหมือนกันแต่ ++ จะทำงานได้ช้ากว่าดังนั้นในกรณีที่เราต้องการเพิ่มอิลิเมนท์เข้าไปที่
หัวของลิสท์ใช้ cons จะทำได้เร็วกว่า

 

edit @ 9 Dec 2009 16:54:57 by cyber-climber

edit @ 15 Dec 2009 11:07:04 by cyber-climber

The Erlang Shell
ต่อไปเราจะเริ่มเปิดเชลของเอิร์ลแลงขึ้นมาเพื่อลองให้งาน โดยในยูนิกส์ให้พิมพ์คำสั่ง "erl" ลงไปมื่อเราสามารถเปิดเชลขึ้นมาแล้ว เราจะเห็นเป็น ( เลขบรรทัด> ) จากนั้นให้ลองพิมพ์ตัวเลขอะไรลงปสักอย่างเพื่อดูผลที่ได้ออกมา (อย่าลืมใส่ . เพื่อแสดงการจบคำสั่ง)
1> −234.
-234
2> 2#1010.
10
3> $A.
65

ในกรณีที่เราไม่ได้ใส่เครื่องหมาย . เข้าไปข้างหลังคำสั่งเอิร์ลแลงจะไม่รู้ว่ามันคือคำสั่งนั่นแปลว่ามันจะเก็บสิ่งที่เราพิมพ์เข้าไปเรื่อยๆจนกว่าเราจะพิมพ์ . เข้าไปนั่นเอง
4> 5-
4>
4> 4.
1
เครื่องหมาย 1>, 2> นั้นคือคอมมานด์พรอมป์ที่แสดงให้เห็นว่าเอิร์ลแลงเชลนั้นพร้อมรับคำสั่งที่เราจะป้อนเข้าไป จากพรอมป์เมื่อเราใส่ตัวเลขและจบด้วยเครื่องหมาย . และกดเอ็นเทอร์ เอิร์ลแลงะรับตำสั่งและทำการแปรออกมาเป็นเลขฐานสิบ แต่ถ้าเกิดข้อผิดพราดเราจะได้เมสเสจออกมาดังนี้
4> 5-.
* 1: syntax error before: '.'
5> q().
ในกรณีที่เราต้องการออกจากโปรแกรมก็สามารถทำได้ด้วยการพิมพ์ q().

Atom
อะตอมในเอิร์ลแลงคือค่าคงที่ที่ไม่ใช่ตัวเลข สำหรับคนที่เคยใช้ภาษาอย่าง C งคุ้นเคยกับการใช้ตัวแปรที่เป็นค่าคงที่เพื่อทำให้โค้ดของเราอ่านได้เข้าใจได้มากขึ้นช่น

#define OP_READ 1
#define OP_WRITE 2
#define OP_SEEK 3
...
#define RET_SUCCESS 223
...
ซึ่งเมื่อเรานำมันมาใช้งานในโปรแกรมหลักผลที่ได้ออกมาจะมีลักษณะนี้
int ret;
ret = file_operation(OP_READ, buff);
if( ret == RET_SUCCESS ) { ... }

ซึ่งโปรแกรมที่เขียนด้วยเอิร์ลแลงนั้นจะออกมาเป็น

Ret = file_operation(op_read, Buff),
if
Ret == ret_success ->
...

การประกาศอะตอมนั้นจะใช้ตัวอักษรตัวเล็กและตามมาด้วยชุดของตัวอักษรตามที่เราต้องการหรือจะเป็น _ หรือt @) เช่น red,ecember, cat, meters, yards, joe@somehost, และa_long_name.นอกจากนี้อะตอมยังสามรถถูกครอบด้วยเครื่องหมาย ' ได้อีกด้วยเนื่องจากในบางกรณีเราต้องการประกาศใช้งานอะตอมที่ขึ้นต้นด้วยตัวหนังสือตัวใหญ่รืออะตอมที่มีตัวอักษรพิเศษเช่น: ’Monday’, ’Tuesday’, ’+’, ’*’,
’an atom with spaces’. ดังนั้นเราจะเห็นว่าค่าของอะตอมใดๆก็คือตัวอะตอมนั่นเอง ดังนั้นเมื่อเราพิมพ์อะตอมลงไปในเชลสิ่งที่เราได้กลับมาคือค่าของอะตอมนั่นเอง
1> hello.
hello
เรื่องนี้ถือเป็นเรื่องค่อนข้างแปลกสำหรับคนที่เคยเขียนภาษาอื่นมาเมื่อเราพูดถึงเรื่องของค่าของอะตอมหรือค่าของอินทิเจอร์ แต่เนื่องจากเอิร์ลแลงเป็นภาษาเชิงฟังก์ชั่นนอล ทำให้ทุกๆคำสั่งหรือการแสดงออก(expression)จำเป็นต้องมีค่า เสมอ

Tuples
ทัปเปิลคือกลุ่มของข้อมูลของเอิร์ลแลง(ต่างชนิดกัน)ที่ถูกเก็บไว้ในรูปแบบของคอลลเล็คชั่นของไอเท็ม ทัปเปิลใช้เครื่องหมายวงเล็บปีกกาเป็นตัวกำหนด, {...}, และแต่ละอิลิเมนท์ของมันจะถูกแบ่งโดยเครื่องหมายลูกน้ำ(commas).
{123, bcd} {123, def, abc} {abc, {def, 123}, ghi} {}
{person, 'Joe', 'Armstrong'} {person, 'Mike', 'Williams'}
ทัปเปิล {123,bcd} ประกอบด้วยสองอิลิเมนท์คือ อิลิเมนท์ที่เป็นอินทิเจอร์ 123 และอิลิเมนท์ที่เป็นอะตอม bcd อีกตัวอย่างของทัปเปอร์
{abc, {def, 123}, ghi} มีสามอิลิเมนท์คือทัปเปิล {def, 123} อีกสองอิลิเมนท์เป็นอะตอมคือ abc และ ghi ส่วน {} แปลว่าทัปเปิลว่างที่ไม่มีสมาชิก ส่วนทัปเปิลที่มีเพียงอิลิเมนท์เดียวเราก็สามารถสร้างได้เช่น {123} แต่ออกจะดูแปลกที่เราจะสร้างของแบบนี้ไว้เพราะเราสามารถเก็บมันไว้บน อันทัปเปิล(untupple) ได้สำหรับทัปเปิลที่มีสมาชิกตัวแรกเป็นอะตอม เราจะเรียกสมาชิกตัวนั้นว่าแทก(TAG) โดยการใช้แทกนี้เป็นข้อตกลงพิเศษทของเอิร์ลแลงที่เราควรรู้ไว้เพราะมันถูกใช้เยอะมาก โดยมากจะใช้เพื่อบอกประเภทของข้อมูลที่เก็บในทัปเปิลเช่น
{person, 'Joe', 'Armstrong'}, อะตอม person จะบอกว่าทัปเปิลนี้ใช้เก็บข้อมูลบุคคลดังนั้นอิลิเมนท์ที่สองของทัปเปิลนี้ควรจะเป็นชื่อ ส่วนอิลิเมนท์  สองก็เป็นนามสกุล สำหรับการใช้แทกนั้นมีเพื่อใช้เพื่อระบุความแต่กต่างของทัปเปิลที่ถูกใช้สำหรับจุดประสงค์ที่ต่างกันในบริเวณต่างๆของโค้ดเรายกตัวอย่างเช่นเราสามารถหาต้นตอของปัญหาที่เกิดขึ้นได้เมื่อมีการส่งทัปเปิลผิดตัวเข้าไปหรือออกมาจากฟังก์ชั่นที่เราเรียกไป
ซึ่งการใช้แทกถือเป็นข้อปฏิบัติที่ดีในการเขียนโปรแกรมด้วยเอิร์ลแลงนอกจากนี้ทัปเปิลยังมีฟังก์ชั่นแบบบิวด์อินมาให้ใช้งานอีกด้วยเช่น

1> tuple_size({abc, {def, 123}, ghi}).
3
2> element(2,{abc, {def, 123}, ghi}).
{def,123}
3> setelement(2,{abc, {def, 123}, ghi},def).
{abc,def,ghi}
4> {1,2}<{1,3}.
true
5> {2,3}<{2,3}.
false
6> {1,2}=={2,3}.
false
คำสั่งที่สองในตัวอย่างที่เราต้องการหาอิลิเมนท์ที่สองแสดงให้เห็นว่าลำดับในทัปเปิลเริ่มด้วยเลข 1 ไม่ใช่ 0
คำสั่งที่สามเป็นการเปลี่ยนค่าอิลิเมนท์ที่สองในทัปเปิล โดยที่ผลที่ได้จะเป็นทัปเปิลใหม่ที่มีค่าตามที่เราต้องการ
โดยที่ทัปเปิลเดิมนั้นค่าก็ยังไม่มีการเปลี่ยนแปลง

เอิร์ลแลง(Erlang) ตอนที่ 3

posted on 04 Dec 2009 14:14 by roofimon  in Erlang
Erlang and Multicore
ปัจจุบันเราหลีกเลี่ยงไม่ได้ที่จะต้องใช้งานซีพียูที่มีหลายคอร์ ซึ่งสำหรับภาษา C และ Java การสร้างแอพพลิเคชั่นให้รองรับการทำงานแบบหลายคอร์นั้นเป็นเรื่องยากมากเพราะมันไม่ได้ถูกออกแบบมาให้มีคุณลักษณะแบบนี้เช่นการทำการดีบั๊กโปรแกรมที่ทำงานแบบขนานใน C และ Javaเป็นเรื่องยากมาก และแน่นอนเอิร์ลแลงทำได้ดีในเรื่องนี้มากๆ เพราะเอิร์ลแลงแตกโพรเซสออกมาโดยไม่มีการใช้เมมโมรี่ร่วมกันและสื่อสารกันผ่านการส่งเมสเสจทำให้มันเหมาะสมกับการทำงานบนซีพียูแบบหลายคอร์และทำให้มันทำงานบนซีฑียูแบบหลายคอร์ได้โดยไม่ต้องออกแบบมันใหม่ทั้งหมด

Symmetric MultiProcessing(SMP) ถูกออกแบบไว้สำหรับเอิร์ลแลงตั้งแต่ปลายช่วง 90 และปัจจุบันมันถูกบรรจุไว้ในรีลีสมาตรฐานเรียบร้อยแล้ว โดยที่ทีมพัฒนาเอิร์ลแลงโอทีพีที่อิริคสันทำการปรับแต่งและปรับปรุงให้เอสเอ็มพีทำงานได้อย่างมีประสิทธิภาพสูงสุด นั่นหมายความว่าตั้งแต่มีการรีลีสเอิร์ลแลงที่มีเอสเอ็มพีออกมา ทำให้ระบบจัดการคิวบนวีเอ็มถูกเปลี่ยนจากการทำงานบนคิวเดียว เป็นการจัดการคิวแบบหลายคิวบนหลายๆคอร์หรือซีพียูนั่นหมายความว่าการจัดการคิวจะไม่ใช่คอขวดของการประมวลผลอีกต่อไป 

หัวใจหลักของเอิร์ลแลงเอวเอ็มพีคือต้องการซ่อนปัญหาและข้อควรระวังต่างๆของเอสเอ็มพีจากโปรแกรมเมอร์เพื่อให้โปรแกรมเมอร์มีสมาธิอยู่กับการพัฒนาโค้ดอย่างที่ตัวเองต้องทำ โดยไม่ต้องมาเสียเวลากับการทำงานพื้นฐานและรวมไปถึงการทำงานร่วมกับระบบปฎิติการและฮาร์แวร์และจำนวนคอร์หรือซีพียูที่ต้องทำงานด้วย โดยที่งานเหล่านั้นจะถูกจัดการโดยเอิร์ลแลงวีเอ็มทั้งหมด

Case Studies
หลังจากเราได้เห็นความสามารถต่างๆของอิร์ลแลงไปบ้างแล้วต่อไปเรามาดูว่า มีกรณีศึกษาใดบ้างที่น่าสนใจในการนำเอิร์ลแลงไปใช้ เราควรจะเริ่มจากอิริคสันก่อนโดยเป็นโปรดักที่ชื่อ AXD301ATM Switch และตามมาด้วยโปรเจคโอเพนซอร์สอีกตัวที่น่าสนใจที่นำเอิร์ลแลงไปใช้งานนั่นคือ CouchDB 
 
The AXD301 ATM Switch
AXD301 เป็น telephony-class 10–160 Gbps เอทีเอ็มสวิทซ์ที่ถูกออกแบบและสร้างจากศูนย์ โดยที่ระยะเวลาการสร้างทั้งหมดใช้เวลาสามปี หัวใจหลักของสวิทซ์ตัวนี้คือซอฟท์แวร์ที่ถูกเขียนด้วยเอิร์ลแลงที่มีความยาวมากว่า 1.5 ล้านบรรทัดที่ทำงานร่วมกับโค้ดที่ทำหน้างานในระดับต่ำและเป็นไดร์เวอร์ที่ถูกเขียนซีและซีพลัสพลัสอีกห้าแสนบรรทัด หน้าที่หลักของเอิร์ลแลงก็คือการควบคุมลอจิกที่ซับซ้อน การจัดการและบริหารพร้อมทั้งการดูแลรักษาเอทีเอ็มสวิทซ์นี้
สวิทซ์ตัวนี้ถูกติดตั้งอย่างแพร่หลายไปทั่วโลกแต่งานที่ทำให้อุปกรณ์ชิ้นนี้มีชื่อเสียงโด่งดังมากคืองานที่บริติชเทเลคอม โดยโปรเจคนั้นรู้กันอย่างกว้างขวางว่าเป็นระบบ "Voice over ATM" ที่ใหญ่ที่สุดในโลกและผลการทำงานหลังจากการทำงานวันแรกของโหนดนี่ในปี 2002 พบว่าระบบมีความน่าเชื่อถือสูงมากระดับ 99.999999% 

แล้วเอิร์ลแลงมีส่วนร่วมในความสำเร็จของ AXD301 อย่างไร เอิร์ลแลงเข้ามาช่วยในเรื่องของการพัฒนาซอฟท์แวร์โดยที่มีผลข้างเคียงหรือผลกระทบน้อยมาก ทำให้ทีมสามารถเพิ่มหรือแก้ไขคอนโพเนนท์ต่างๆได้เนื่องจากเอิร์ลแลงมีความสามารถในเรื่องของความยืดหยุ่นและการทำงานแบบพร้อมกัน มาให้เรียบร้อยแล้ว ด้วยความสามารถนี้ทำให้เอิร์ลแลงได้รับการยอมรับอย่างสูงในทีมพัฒนาเพราะโค้ดที่ได้จะมีขนาดกระทัดรัดสมเหตุสมผล และถ้าเปรียบเทียบกับภาษาอื่นๆเช่น ซี/ซีพลัสพลัส จาวา หรือ เพล็ก* แล้วโค้ดของเอิร์ลแลงมีขนาดสั้นกว่า 4 ถึง 10 เท่า

จากความสำเร็จของโปรเจคนี้ทำให้อิริกสันนำเอิร์ลแลงไปใช้ในโปรเจคอื่นๆอีกหลายโปรเจคไม่ว่าจะเป็น SIP telephony stack, ซอฟท์แวร์ที่ใช้ในการควบคุมสถานีแบบไร้สาย, telephony gateway,media gateways, broadband solutions, and in GPRS and 3G data transmission.

CouchDB
เมื่อนายเดเมี่ยน แคทซ์ตัดสินใจที่จะสร้างเคาช์ดีบีเค้าต้องการที่จะพัฒนาอะไรที่มัน "แจ๋ว" เค้าเองต้องการที่จะพิสูจน์ตัวเองว่าตัวเองมีความสามารถมากพอที่จะพัฒนาอะไรสักอย่างจากศูนย์หรือไม่สิ่งที่เค้าต้องการทำคือฐานข้อมูลที่ถูกสร้างบนพื้นฐานของ schema-less replicated document store, และเก็บออบเจคในรูปแบบของ JSON, ข้อมูลเหล่านั้นจะถูกใช้งานป่าน RESTful 

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

เอิร์ลแลงมีคุณสมบัติครบตามที่เดเมียนต้องการเพื่อสร้างฟังก์ชั่นการทำงานพิเศษให้เคาช์ดีบีทุกข้อ เขาจึงเริ่มย้ายโค้ดเปลี่ยนไปเป็นเอิร์ลเลงสำหรับส่วนของการทำงานแบบพร้อมกันหลายโพรเซสแทนที่โค้ดเดิมที่เป็นซีพลัสพลัส แต่สุดท้ายแล้วโค้ดทั้งหมดของเคาช์ดีบีถูกเขียนใหม่ทั้งหมดเป็นเอิร์ลแลง!!!! เนื่องจากเอิร์ลแลงมีสิ่งที่เขาต้องการในการสร้างระบบฐานข้อมูลเช่น ระบบจัดการไอโอที่แข็งแรงมาก มีความน่าเชื่อถือสูง กระบวนการจัดการกับเออร์เร่อร์ที่ดี และหลังจากทำการทดสอบเปรียบเทียบสมรรถนะแอพพลิเคชั่นตัวใหม่(ยังไม่ได้ปรับแต่งโค้ด) พบว่ามันสามารถรับโหลดได้ประมาณ
20,000 คอนเน็กชั่นพร้อมกัน ซึ่งเมื่อเทียบกับแอพพลิเคชั่นตัวเดิมที่เป็นซีพลัสพลัสซึ่งรับได้เพียง 500 คอนเน็กชั่นเท่านั้น !!! ตอนนี้เคาช์บีดีถือเป็นโปรเจคที่มีชื่อเสียงมากที่ถูกเขียนด้วยเอิร์ลแลงและโค้ดของโปรเจคนนี้เป็นแหล่ง
ที่ใช้ศึกษาเกี่ยวกับเอิร์ลแลงที่ดีมาก

เอิร์ลแลง(Erlang) ตอนที่ 2

posted on 03 Dec 2009 09:46 by roofimon  in Erlang
High-Level Constructs
เอิร์ลแลงเป็นภาษาเชิงบอกเล่า(declarative) โดยที่ลักษณะเด่นของภาษาแบบนี้คือตัวมันเองจะอธิบายว่าอะไรควรจะถูกคำนวณ ไม่ใช่ว่าค่าที่ได้มานี้ถูกคำนวณมาอย่างไร(โคตรงง) ในเอิร์ลแลงการประกาศฟังก์ชั่นจะใช้กระบวนการเปรียบเทียบแพทเทิร์น(Pattern Matching) เพื่อเลือกว่าฟังก์ชั่นใดควรทำงาน นอกจากนี้เรายังใช้กระบวนการนี้เข้ามาช่วยในการดึงเอาข้อมูลอะไรบางอย่างออกมาจากโครงสร้างข้อมูลที่ซับซ้อน ดังนั้นการทำการเปรียบเทียบแพทเทิร์นนั้นจะมองแล้วเหมือนชุดของสมการทางคณิตศาสตร์เช่น

area({square, Side}) -> Side * Side ;
area({circle, Radius}) -> math:pi() * Radius * Radius.

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

decode(<< SourcePort:16, DestinationPort:16,
SequenceNumber:32,
AckNumber:32,
DataOffset:4, _Reserved:4, Flags:8, WindowSize:16,
Checksum:16, UrgentPointer:16,
Payload/binary>>) when DataOffset>4 ...

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

qsort([]) -> [];
qsort([X|Xs]) ->
qsort([Y || Y<-Xs, Y =< X]) ++ [X] ++ qsort([Y || Y<-Xs, Y > X]).

Concurrent Processes and Message Passing
การทำงานของโพรเซสพร้อมๆกันในเอิร์ลแลงเป็นความสามารถพื้นฐานของมันอยู่แล้วและสำหรับเอิร์ลแลงแล้ว
มันจะทำการสร้างโพรเซสที่มีรีซอร์สเป็นของตัวเองออกมาทุกครั้งแทนที่จะสร้างเทรดที่ใช้รีซอร์สร่วมกันเนื่องจากมันต้องการป้องกันปัญหาในเรื่องของการรบกวนกันของเทรด ซึ่งอาจจะนำมาซึ่งปัญหาเรื่องของเดดล๊อคได้

การสื่อสารระหว่างโพรเซสนั้นจะถูกทำผ่านการส่งเมสเสจ โดยที่เมสเสจนั้นสามารถเป็นประเภทของข้อมูลทุกๆอย่างในเอิร์ลแลงและมันเองจะทำงานในภาระเวลาที่แตกต่างกัน(Asynchronous)นั่นหมายความว่าเมื่อโพรเซสทำการส่งเมสเสจออกไปแล้วมันเองก็สามารถทำงาน อื่นๆต่อเนื่องไปได้เลย และเมสเสจเหล่านั้นเองก็จะถูกโพรเซสดึงออกมาจากกล่องจดหมาย(mail box)ได้ตามความต้องการ โดยไม่ต้องคำนึงถึงลำดับของเมสเสจที่ถูกส่งเข้ามา ซึ่งความสารถนี้จะช่วยให้เราสามารถการประมวลผลแบบการจายได้อย่างยืดหยุ่นมาก เนื่องในการเขียนโปรแกรมแบบกระจายข้ามเน็ทเวิร์คนั้นลำดับของเมสเสจอาจไปขึ้นตรงกับระดับการทำงานของเน็ทเวิร์คมาก จนทำให้เมสเสจเหล่านั้นเข้ามาช้าผิดปกติได้ซึ่งเราเองก็รอไม่ได้เช่นกัน

Scalable, Safe, and Efficient Concurrency
การทำงานแบบพร้อมกันของโพรเซสในเอิร์ลแลงนั้น เร็ว และขยายออกไปได้ง่ายมากเนื่องจาก โพรเซสต่างๆที่เกิดขึ้นจะถูก สร้าง จัดตาราง และจัดการทำงานอยู่ภายใต้ เอิร์ลแลงวีเอ็มซึ่งจะเป็นอิสระจากระบบปฏิบัติการที่อยู่ในระดับต่ำลงไปกว่า ทำให้ช่วงเวลาที่ใช้ในการสร้างโพรเซสอยู่ในระดับไมโครวินาที และไม่ขึ้นกับจำนวนโพรเซสที่ถูกสร้างไว้ก่อนหน้านี้แล้ว ซึ่งเมื่อเราเปรียบเทียบสิ่งนี้กับ Java หรือ C# แล้วจะเห็นว่าทั้งสองภาษานั้นจะสร้างโพรเซสภายใต้ระบบปฎิบัตการโดยตรงทำให้เราต้องไปแข่งขันกับระบบอื่นอย่างยากลำบากเพื่อขอใช้รีซอร์ส นอกจากนี้เอิร์ลแลงยังสื่อสารกันระหว่างโพรเซสด้วยการส่งเมสเสจและกระบวนการส่งก็เป็นเพียงแค่การคัดลอกข้อมูลจากเมมโมรี่สเปซหนึ่งไปยังอีกที่หนึ่งเท่านั้น
ทำให้กระบวนการส่งเมสเสจเป็นไปได้อย่างรวดเร็ว 

Soft Real-Time Properties
ถึงแม้ว่าเอิร์ลแลงจะเป็นภาษาระดับสูงแต่มันเองก็สามารถถูกใช้สำหรับงานประเภทซอฟท์เรียลไทม์ได้เนื่องจากหลายปัจจัยเช่นการจัดการการใช้รีซอร์สทำผ่านกระบวนการการ์เบจคอลเลคชั่นในด้วยโพรเซสเองเลยทำให้มันทำงานได้เร็วมากนั่นแปลว่ามันทำการรับโหลดได้สูงมากโดยที่ผลตอบสนองไม่ตกแม้กระทั่งในช่วงเวลาที่โหลดสูงกมาก็ตาม

Roburstness
เราจะสร้างระบบที่มีความยืดหยุ่นได้ดย่างไร ในเมื่อเอิร์ลแลงเองก็ทำได้เหมือนกับภาษาเชิงฟังก์ชั่นนอลทั่วไป แต่สิ่งที่ทำให้เอิร์ลแลงแต่ต่างคือกระบวนการจัดการข้อผิดพลาดและการเฝ้าระวังข้อผิดพลาดที่ถูกออกแบบไว้อย่างยืดหยุ่นในใจกลางของตัวภาษาเอง ไลบรารี่พิเศษนี้มีชื่อว่า โอทีพี และยังมีไลบรารี่อื่นๆที่ถูกสร้างอยู่บนตัวโอทีพีอีกเช่น

โพรเซสของเอิร์ลแลงสามารถถูกเชื่อมเข้าด้วยกันดังนั้นเมื่อมีโพรเซสใดตายไป โพรเซสอื่นๆที่เชื่อมอยู่ด้วยกันจะได้รับการแจ้งเตือนหลังจากนั้นโพรเซสที่เหลือก็ต้องตัดสินใจว่าจะจัดการกับเออร์เร่อร์อย่างไรหรือว่าจะหยุดการทำงานตัวเองลงไปด้วย

โอทีพี เตรียมไลบารี่พื้นฐานที่จำลองพฤติกรรมพื้นฐานสำหรับการทำงานบางอย่างไว้ให้เราใช้งานเช่น ไลบรารี่การทำเซิร์ฟเวอร์ไลบารี่สำหรับไฟไนท์สเตทแมทชีน และแน่นอนว่าไลบารี่พิเศษพวกนี้ยังคงไว้ซึ่งความยืดหยุ่นในการทำงานไว้เนื่องจากมันเป็นความสามารถพื้นฐาน(ที่ทำได้ยากมากในภาษาอื่น)ของเอิร์ลแลง ดังนั้นโปรแกรมเมอร์จะต้องทำก็เพียงแค่เขียนสิ่งที่ตัวเองต้องการเพิ่มเข้าไปในระบบพื้นฐานที่เอิร์ลแลงเตรียมไว้ให้แล้ว นั่นหมายความว่าเราจะงานได้เร็วขึ้นมาก เพราะเราไม่ต้องมัวเสียเวลาเขียนสิ่งที่เป็นพื้นฐานเองตั้งแต่แรก

พฤติกรรมพื้นฐานเหล่านี้ยังถูกเชื่อมเข้ากับคนควบคุมพฤติกรรมที่ทำหน้าที่ตรวจตราและจัดการการบวนการเกี่ยวกับการหยุดโพรเซส ซึ่งแนวคิดการเชื่อมโพรเซสเข้าด้วยกันแบบคนงานกับหัวหน้างานเป็นอีกแนวคิดหลักของเอิร์ลแลงเพื่อให้มีการตรวจสอบกันเป็นชั้น ไปเรื่อยๆตามที่เราต้องการ

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

Distributed Computation
อย่างท่เรารู้กันแล้วว่าการประมวลผลแบบกระจายเป็นความสามารถพื้นฐานของเอิร์ลแลง โดยที่ฟังก์ชั่นการทำงานนี้เอิร์ลแลงโดยปกติจะทำงานบน ทีซีพี/ไอพี ดังนั้นทุกโหนดบนระบบเน็ทเวิร์คใดๆก็ตามสามารถต่อเข้าหากันได้ ตราบเท่าที่โหนด
เหล่านั้นทำงานบน ทีซีพี/ไอพี และไฟร์วอลถูกกำหนดค่าอย่างถูกต้อง

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

Integration and Openness
เนื่องจากในชีวิตจริง เราต้องทำงานกับแพลทฟอร์มและภาษาต่างๆที่หลากหลายมาก ตัวเอิร์ลแลงเองก็สามารถทำงานกับภาษาต่างๆหลายภาษาได้เช่น C, Java,Ruby, Python, Perl, LIPS และอื่นๆด้วยไลบรารี่ระดับสูงในเอิร์ลแลง ทำให้เราสามารถมองโหนดอื่นๆที่มีแอพพลิเคชั่นที่ถูกเขียนด้วยภาษาอื่นเช่น Java, C ให้เป็นเอิร์ลแลงโหนดได้และนอกจากนีเราสามารถเชื่มภาษาเหล่านั้นเข้ากับเอิร์แลงได้อย่างแนบแน่นด้วยการใช้ไดร์เวอร์เพื่อเชื่อมเข้ากับเอิร์แลงวีเอ็ม ทำให้เรามองมันเป็นเหมือนอุปกรณ์ชนิดหนึ่งที่เราสามารถเปิดซ๊อกเก็ทเพื่อสื่อสารกันได้ โดยการสื่อสารสามารถทำป่านโปรโตคอลยอดนิยมอย่าง HTTP, SNMP และ IIOP

อีกหนึ่งความสามารถที่เอิร์ลแลงเตรียมไว้ให้สำหรับการประมวลผลแบบกระจายคือ การจัดการกับฟอร์แม็ทของข้อมูลบนเน็ทเวิร์ค เพราะเอิร์ลแลงเตรียทการบวนการทำล๊อกกิ้งไว้ให้เราเพื่อให้เราสามารถตรวดดูการทำงานมันได้อย่างชัดเจน

edit @ 3 Dec 2009 15:01:02 by cyber-climber

เอิร์ลแลง(Erlang) ตอนที่ 1

posted on 02 Dec 2009 15:11 by roofimon  in Erlang

ไม่ได้เขียน blog ที่นี่นานมากอยากเขียนเรื่องเอิร์ลแลงเก็บไว้อ่านเองไม่รู้จะไปเขียนที่ไหนก็เลยนึกถึงที่นี่ก่อน แต่!!!ไม่ได้เข้ามานาน แน่นอนลืมรหัสผ่านพยายามมั่วอยู่หนึ่งคืนก็ทนไม่ได้ ต้องกดสูตรลับ ผมก็ได้รหัสใหม่มาภายในสิบนาที

 ทำไมต้องเอิร์ลแลง(Erlang)ภาษาอื่นก็มีตั้งมากมายล้านแปดที่จะให้ไปอ่านเล่นไม่ว่าจะเป็น สกาล่า(Scala), รูบี้(Ruby), ไพธอน(Python) และอื่นๆอีกมากมายแต่สำหรับผมแล้วมีเหตุผลอยู่สองข้อ

 

  • ภาษานั้นต้องไม่ทำงานบนเจวีเอ็ม เพราะผมเบื่อมันมากกกกกก
  • ภาษานั้นต้องไปเป็นการเขียนโปรแกรมแบบเชิงวัตถุ(Object Oriented) เพราะอยากเปลี่ยนวิธีคิดบ้าง 

 

ดังนั้นหวยเลยออกที่เอิร์ลแลง ก่อนอื่นเรามาทำความรู้จักกับภาษาก่อนว่ามันคืออะไร

1.1 เอิร์ลแลงในเปลือกนัท

เอิร์แลงเองเป็นทั้งแพลทฟอร์มและเป็นภาษาสำหรับการใช้งานทั่วไป โดยที่ตัวมันเองถูกออกแบบมาให้สามารถรองรับการทำงานหลายๆงานพร้อมกัน(Concurrent), กระจายการทำงาน(Distribution) และทนต่อความผิดพลาด(Fault Tolerance)ดังนั้นเราจะเห็นการนำเอาภาษานี้ไปใช้งานในโดเมนของระบบการสื่อสารเยอะมากเช่นบริษัทอิริกสัน(Ericsson)เป็นบริษัทที่ใช้งานภาษาเอิร์ลแลงสำหรับการสร้างระบบสื่อสารขนาดใหญ่ของตัวเองเยอะมาก
 

1.2 อะไรคือโอทีพี(OTP)

โอทีพีเป็นคำย่อของมาตรฐานเทเลคอมแบบเปิด(Open Telecom Platform)  ตัวมันเองเป็นไลบารี่ขนาดใหญ่ที่ช่วยให้เราสามาถทำได้ตั้งแต่การคอมไพล์ Abstract Syntax Notation One (ASN.1) ไปจนถึงการเตรียมเวบเซิร์ฟเวอร์ ดังนั้นทุกโปรเจคที่ใช้เอิร์ลแลงส่วนใหญ่จะใช้ เอิร์ลแลง/โอทีพี ไปโดยธรรมชาติแล้วนั่นเอง

1.3 แอพพลิเคชั่นประเภทไหนที่ควรจะใช้เอิร์ลแลง

 

  • การประมวลผลแบบกระจาย, งานที่ต้องการความน่าเชื่อถือสูงมาก และการทำงานแบบซอฟท์เรียวไทม์
  • ระบบทางโทรคมเช่นการควบคุมสวิช, การแปลงโปรโตคอล
  • เซิร์ฟเวอร์สำหรับอินเทอร์เน็ทแอพพลิเคชั่น ยกตัวอย่างเช่น เอเจนท์สำหรับส่งเมล์ เซิร์ฟเวอร์ IMAP-4,HTTP เซิร์ฟเวอร์หรือ WAP สแต็ค.
  • แอพพลิเคชั่นของระบบโทรคม เช่น การควบคุมระบบเน็ทเวิร์คสำหรับโทรศัพท์เคลื่อที่ 
  • แอพพลิเคชั่นทั่วไปที่ต้องการความสามารถระดับซอฟท์เรียวไทม์

 

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

 

  • เอิร์ลแลงเตรียมกระบวนการการจัดการที่เรียบง่ายและทรงพลังสำหรับการจัดการเออร์เรอร์และข้อผิดพลาดต่างๆ 
  • การทำงานในเวลาเดียวกันและการส่งเมสเสจเป็นความสามารถพื้นฐานของตัวภาษาเอง ดังนั้นแอพพลิเคชั่นที่ถูกเขียนด้วยเอิร์ลแลงเองมักจะแตกโพรเซสขนาดเล็กออกมาเป็นจำนวนนับร้อยเพื่อทำงานอะไรบางอย่างให้สำเร็จและกระบวนการสลับลำดับของแมกนิจูดของโพเซสขึ้นไปหนึ่งหรือสองลำดับในเอิร์ลแลงนั้นไม่ได้เป็นเรื่องยากอย่างที่เราต้องทำกันในภาษาซี
  • การเขียนแอพพลิเคชั่นให้มีการประมวลผลกระจายไปหลายๆเครื่องสามารถทำได้อย่างง่ายดาย เพราะกระบวนการการะจายงานอันซับซ้อนนั้นถูกซ่อนไว้อย่างแนบเนียนในเอิร์ลแลง โดยที่โปรแกรมของเราไม่จำเป็นต้องรู้ตัวเองว่ามันกำลังประมวลผลแบบกระจายอยู่
  • โอทีพีไลบรารี่เองช่วยเราแก้ปัญหาพื้นฐานต่างๆในการทำงานบนระบบเน็ทเวิร์คและระบบโทรคมไว้แล้ว 

 

เอิร์ลแลงมีตัวรันไทม์เอ็นไวรอนเมนท์ของเอิร์ลแลง(เหมือนกับเวอร์ชวลแมชีนของจาวา)  นั่นหมายความว่าโค้ดเอิร์ลแลงของเราสามารถถูกนำไปรันได้ทุกๆที่ที่มีตัวรันไทม์อยู่ 

 

1.4 ใครใช้งานเอิร์ลแลงอยู่บ้าง

คนที่ใช้งานเอิร์ลแลงมากที่สุดก็คืออิริกสัน โดยระบบที่ใหญ่ที่สุดของอิริคสันที่ใช้เอิร์ลแลงคือ AXD301 ATM Switch โดยปริมาณที่โค้ดของเอิร์ลแลงที่ใช้สำหรับโปรเจคนี้คือ 850 kloc และ 1Mloc ของ C/C++

บริษัทอื่นๆที่ใช้งานเอิร์ลแลง

 

  • Bluetail/Alteon/Nortel (distributed, fault tolerant email system, SSL accelerator) 
  • Cellpoint (Location-based Mobile Services) 
  • Corelatus (SS7 monitoring). 
  • dqdp.net (in Latvian) (Web Services). 
  • Facebook (Facebook chat backend) 
  • Finnish Meteorological Institute (Data acquisition and real-time monitoring) 
  • IDT corp. (Real-time least-cost routing expert systems) 
  • Kreditor (Electronic payment systems) 
  • Mobilearts (GSM and UMTS services) 
  • Netkit Solutions (Network Equipment Monitoring and Operations Support Systems) 
  • Process-one (Jabber Messaging) 
  • Schlund + Partner (Messaging and Interactive Voice Response services) 
  • Quviq (Software Test Tool) 
  • RabbitMQ (AMQP Enterprise Messaging) 
  • T-Mobile (previously one2one) (advanced call control services) 
  • Telia (a telecomms operator) 
  • Vail Systems (Interactive Voice Response systems) 
  • Wavenet (SS7 and IVR applications) 

 

 

 

 

 

 

@chanwit ได้รับแรงบันดาลใจจากรายงานการเลือกตั้งประธานาธิปดี ประเทศเจ้าโลกครับ โดยมีคนเก่งเขียนแอพพลิเคชั่นดึงเอาข้อความต่างๆ ที่มีคนพูดถึงผู้สมัคร

@chanwit เลยเขียนแอพพลิเคชั่นมาอีกหนึ่งตัวที่ดึงเอาข้อความใน twiiter ทีทีคนพูดถึงผู้สมัคร 5 คนขึ้นมให้เราอ่านประกอบไปด้วย ประภัสร์ อภิรักษ์ ลีน่า ชูวิทย์ และ เกรียงศักดิ์ ใครสนใจติดตามข่าวสารแบบรวดเร็วทันใจสามารถเข้าไปลองเล่นได้ที่

เลือกตั้งผู้ว่ากรุงเทพ 51<< click ที่นี่ครับ

 

edit @ 30 Sep 2008 22:42:24 by cyber-climber

อยากใช้ Rich Internet Application

posted on 23 Jul 2008 10:34 by roofimon  in computer

อยากใช้ครับเพราะช่วงหลังเรื่องนี้แรงมาก เหตุผลเพราะอันดับแรกเน็ทมันแรงขึ้นทำให้เราสามารถใส่คอนเทนท์ที่พิศดารได้มากขึ้น รวมทั้งขนาดใหญ่มากขึ้น

ทำให้ผู้ผลิตเจ้าใหญ่ๆเร่งปล่อยของออกมากันใหญ่ทั้ง Adobe, SUN, MS ของฟรีก็มีหลายเจ้า

Adobe-Flex3 ต้นตำหรับตัวพ่อเรื่อง RIA เป็นเจ้าแรกที่ปล่อยเครื่องมือในการทำงานออกมาเจ้าแรก โดยออกมาตั้งแต่ปี 2004 สำหรับ Flex 1.0 ซึ่งตอนนั้นฮือฮามากเนื่องจาก เราสามารถสร้างแอพพลิเคชั่นให้หลุดพ้นจากขอบเขตเดิมๆที่เราติดอยู่ได้ แต่เงื่อนไขคือราคาแพงมากๆ ปัจจุบันมาถึงเวอร์ชั่นสามแล้ว มหัศจรรย์มากครับ แถมทั้งไม่เสียเงินด้วยถ้าต้องการเขียนเองโดยไม่ต้องพึ่งพาเครื่องมือ และที่บอกมหัศจรรย์คือมันสามารถเขียนรวมกับภาษาได้หลากหลายมากๆ ที่สนุกที่สุดคือเขียนกับ Rails ได้เนียนมากแถมมีหนังสืออกมาสองเล่มคือ Flexible Rails และ Enterprise Flexible Rails ดังนั้นไม่ต้องกลัว (ผมชอบแนวนี้มาก) ใครยังไม่เคยดูก็แวะไปดูได้ว่ามันตื๊ดขนาดไหนที่ Flex Showcase

SUN-JavaFx ออกมาให้ตื่นเต้นเล่นก่อน แล้วก็เงียบเป็นเป่าสาก แต่คาดว่ากำลังซุ่มทำอะไรแนวๆอยู่เพราะจาก JavaOne ครั้งที่ผ่านมาเห็นเอา ของเล่นมาโชว์คือสามารถทำให้ designer กับ developer ทำงานได้ใกล้กันมากขึ้นเพราะสามารถเอางานที่ designer ทำใน Photoshop ทำการ export ออกมาเขียนต่อได้เลยไม่ต้องเสียเวลาตัดให้เนิ่นนาน แต่ก็ยังเงียบเหมือนเดิม

MS-Silverlight2 ดีครับมหัศจรรย์มากๆเพราะออก expression studio มาด้วยเลยทำให้ Adobe ร้อนๆหนาวๆแต่ติดตรงเรื่องราคามหาโหด ตอดมาแบบเย็นๆ แต่รวมกันถึงสะดุ้งไปดูงานได้ที่ Showcase ครับสำหรับคนที่เป็นสาวกคงชอบมากเพราะมันก็ทำให้เรา ทำอะไรแปลกๆได้อีกเหมือนกันและถ้าดูจากผลที่ได้อาจจะลืมเรื่องราคาไปได้เหมือนกันครับ และที่สำคัญ Microsoft เตรียมคลังข้อมูลมหาศาลไว้ให้เรียบร้อยแล้ระดับไม่เสียดายตังแม้แต่แดงเดียวที่จ่ายไป

ส่วนที่เหลือก็จะเป็น product ที่ดังเมืองนอกอย่าง backbase แต่ไม่ดังเมืองไทยอันนี้ก็ครบชุดแต่แพงนรกแตก ส่วนอีกตัวคือ OpenLazlo ที่ยืนกรานว่าตัวเองเป็น Flex Alternative ดูจาก demo น่าสนใจครับแต่เอกสารน้อยจนน่ากลัว

สรุปผมน่าจะไปทาง Flex (+Rails) ครับเพราะดูแล้วจะกลางๆและมีอนาคตที่สุดสำหรับผม

เกริ่น

CPU คุณมีกี่ Core ครับ? ใครตอบต่ำกว่าสองคอร์ถือว่าตกเทรนด์ครับเพราะเดี๋ยวนี้เราต้องมีหลายๆคอร์และจากการ ทำนายแล้วในอีกสองปีเราจะมี CPU ที่มี 32 คอร์ออกมาให้เล่น

ทำไมต้องมีคอร์เยอะๆ คำตอบสามารถถามได้จากเพื่อที่เรียนคอม เพราะมันเป็นเรื่องคลาสสิค นั่นคือหลักการของมัวร์ นายมัร์กล่าวไว้ว่า

กฎของมัวร์ กล่าวไว้ว่า "คอมพิวเตอร์จะมีความเร็วเพิ่มขึ้นเป็นสองเท่า ทุก ๆ 18 เดือน โดยที่มีราคาคงเดิม" แต่ผู้เชี่ยวชาญในด้านนี้แตกต่างกันค่อนข้างมากครับ เพราะเป็นเรื่องของการทำนายอนาคต ผู้เชี่ยวชาญหลายท่านและ Dr. Moore เองก็คิดว่า กฎนี้น่าจะไปเจอทางตันที่ประมาณปี 2020

เพราะอย่าลืมว่าเราจะทำ ทรานซิสเตอร์ให้มันเล็กลงไปได้มากขนาดไหนกันละ? ดังนั้นหนึ่งในทางออกคือเพิ่มคอร์เข้าไป แทนที่จะเพิ่มความเร็วให้คอร์เดียว ก็ใส่คอร์ไปเยอะๆแต่ความเร็วของแต่ละคอร์ลดลงอันนี้เอามาจาก (http://softwareblogs.intel.com/2007/03/14/the-multi-core-dilemma-by-patrick-leonard/)

นั่นคือสิ่งที่จะเกิดกับเราและเราหนีไม่พ้น สิ่งที่จะกระทบกับกรรมกรไซเบอร์อย่างเราคือ การเขียนโปรแกรมแบบเดิมๆ จะทำให้ แอพพลิเคชั่นของเราช้าลง (กรำแท้ๆ) เนื่องจากภาษาที่เราใช้อยู่นั้นไมได้ออกแบบมาให้ทำงานบนสถาปัตยกรรมหลายคอร์แล้วเราจะทำอย่างไรดีกับการเปลี่ยนแปลงที่กำลังเยื้อย่างเข้ามาเราอีกครั้ง

ทางเลือกแรก

ภาษาใหม่เท่านั้นที่เราต้องเตรียมตัวไว้ ไม่มีทางเลือก ภาษาที่ถูกออกแบบมาให้ทำงานบนโลกหลายคอร์นั้นตอนนี้ที่ ดังๆมีสองภาษาคือ Erlang และ Scala ครับผมเองรู้จักคำว่า Erlang มาประมาณหนึ่งปีที่แล้วจากพี่ป๊อกเจ้าพ่อเด็กแนวส่วน Scala นั้นก็เพิ่งรู้จักเมื่อหกเดือนที่แล้วจากพี่ป๊อกอีกนั่นแหละ

ทั้งสองภาษานี้เป็นภาษาแห่งอนาคตครับ Scala เองเป็นภาษาที่ถูกเรียกว่าเป็นผู้สืบทอดแห่ง JVM หลายคนฟันธงว่ามันจะมาแทน Java และตัวมันเองถูกสร้างมาด้วยการเอาแนวคิดเรื่อง Object Oriented Programming มาผสมเข้ากับ Functional Programming ได้อย่างสวยงาม

ในทางกลับกัน Erlang เกิดขึ้นมาโดยบริษัท Ericsson โดยมันถูกออกแบบมาให้รับมือกับงานประเภท distributed, fault-tolerant, soft-real-time, non-stop applications แต่แตกต่างตรงที่มันเป็น Functional Programming

ทางเลือกที่สอง

ภาษาเก่าสิ่งที่เราต้องทำคือลุ้นว่าจะมีคน port ภาษาที่เราใช้อยู่ให้มันสามารถทำงานได้ดีบนโลกหลายคอร์ได้หรือไม่ เรามาดูกันทีละภาษา

Ruby เท่าที่เห้นว่าจะเป็นไปได้มากที่สุดคือ Rubinius ที่ประกาศว่าจะสร้าง VM สำหรับ Ruby ที่สามารถทำ  rich, high-performance environment for running Ruby code ที่เหลือดูจะยังไม่เป็นเรื่องเท่าไหร่

Python มี thread อยู่แล้วแต่ thread ใน python เป็น user thread ดังนั้นจะไม่สามารถแตก thread ข้ามคอร์ได้

Java มีอยู่แล้วสบายด้วย

C# ไม่ขอเอ่ยเพราะไม่รู้เรื่อง

จบเท่านี้ครับ

 

 

 

edit @ 24 Jun 2008 15:45:54 by cyber-climber