Tail Recursion

การทำงานของโปรแกรมโดยทั่วไปเวลาเรียก function นั้นจะมีการจำตำแหน่งที่เรียกเอาไว้แล้วกระโดดเข้าไปทำงานใน function เมื่อเจอคำสั่ง return ก็จะกระโดดกลับมา ดั้งนั้นถ้ามีการเขียนแบบ recursive ก็จะมีการสร้าง stack ของการ call function ซ้อนๆกันไว้ แล้วพอ return ก็จะย้อนกลับมาทีละ step นี่คือกรณีของ recursive แบบธรรมดาทั่วๆไป ซึ่งจะเห็นว่าจะต้องเสียเวลาในการกระโดดกลับมา

Tail Recusion นั้นจะช่วยลดการทำงานตรงนั้นได้โดยแทนที่จะรอให้ได้ผลลัพธ์เมื่อมีการย้อน กลับ ก็จะทำการเก็บผลลัพธ์ตั้งแต่การเรียก recursive function จนเมื่อถึง การ call ครั้งสุดท้ายก็จะเป็นการ return ผลลัพธ์ออกมาทันที ไม่ต้องย้อนกลับไปอีก

ตัวอย่าง ฟังก์ชัน หาความยาวของ list ถ้าเขียนแบบ recursive ธรรมดา ได้แบบนี้


mylength :: [a] -> Int

mylength [] = 0
mylength (y:ys) =  1+mylength (ys)

จะเห็นว่าแบบนี้ terminate function จะรับค่า empty list แล้ว return 0 ออกมา เมื่อมีการ recursive ก็จะเอา 1 ไปบวกไป แบบนี้จะเกิดการ call ไปจนสุด แล้วค่อยเอาค่า มาบวกกันทีหลังแบบนี้


mylength "abc" -> 1+mylength("bc")
                        -> 1+1+mylength("c")
                        -> 1+1+1+mylength("")
                        -> 1+1+1+0
                        -> 1+1+1
                        -> 1+2
                        -> 3

แต่ถ้าเขียนแบบ tail recursive เราจะเพิ่มตัว accumulator เข้ามา ตัว accumulator ก็คือ พารามิเตอร์ที่เก็บ ผลลัพธ์ในแต่ละ step ที่ทำการ recursive เมื่อ terminate ที่เป็นการ call ครั้งสุดท้ายเราจะ return ค่า accumulator ออกมาทันที


mylength :: [a] -> Int
mylength ys =  _mylength ys 0
_mylength [] n = n
_mylength (y:ys) n = _mylength ys (n+1)

ตัวอย่างนี้เราเขียน function _mylenth ขี้นมาเป็น tail recursion แล้วตัวfunction mylength ของเรา ก็ค่อย call _mylength โดยส่งค่า 0 เป็นค่าเริ่มต้นของ accumulator

Leave a comment »

Unicode in Coldfusion

เนื่องจากว่ามันมีให้เซตหลายๆแบบ หลายๆจุด จะใช้ทีลืมประจำ ก็blogไว้ซะหน่อย

  1. เอาโค้ดนี้ ไปไว้ใน Application.cfc
    
    <cfscript>
        SetEncoding("form","utf-8");
        SetEncoding("url","utf-8");
    </cfscript>
    

    แบบนี้คือบอกว่าข้อมูลที่อยู่ใน scope form และ url ใช้ utf-8

  2. 
            <cfcontent type="text/html; charset=utf-8">
    

    โค้ดนี้บอกว่า template ที่เปิดเป็นไฟล์แบบ text/html และ ใช้ charset เป็น utf8
    โดยโค้ดนี้ต้องอยู่ส่วนบนสุดของไฟล์

  3. 
            <cfprocessingdirective pageEncoding="utf-8">
    

    อันนี้ก็เอาไปวางได้ทุกๆ template ที่มีการติดต่อ db หรือว่ามี i/o กับ browser
    ถ้าใช้กับ coldbox ก็สามารถ เอาไปว่างไว้ที่ Layout ที่เดียวได้เลย

Leave a comment »

Tree In Haskell

ตอนนี้กำลัง ค่อยๆ ไล่อ่าน หนังสือ Real World Haskell ที่ร่วมกันเขียนโดย  Bryan O’Sullivan, Don Stewart, and John Goerzen
หนังสือตีพิมพ์เป็นเล่มขายแล้ว อยากซื้อเก็บเหมือนกัน แต่ก็ไม่เคยซื้อผ่าน amazon ไม่มีพวกบัตรเครติด อะไรเลย ก็เลยยังไม่ซื้อ

หนังสือเล่มนี้ มีให้อ่านออนไลน์ผ่านเว็บ http://book.realworldhaskell.org/ ที่จริง หนังสือเล่มนี้ก่อนตีพิมพ์ ผู้แต่งเขาก็เอาขึ้นเว็บ
ให้อ่าน และก็ให้ comment ในแต่ละ paragraph ได้ในระหว่างแต่ง เพราะฉนั้นถ้าเข้าไปอ่านจะเห็นว่าในแต่ละ paragraph จะมีลิ้ง
ให้ comment ได้

มาว่ากันตามหัวข้อ คือ เขียนโครงสร้างข้อมูลแบบ Tree ด้วย Haskell ซึ่งมันเป็นแบบฝึกหัดอยู่ที่บทที่ 3 ว่าให้สร้าง data type Tree
โดยให้มี variable constructor ตัวเดียว โดยใช้ data type Maybe a เข้าช่วย นั่งทำอยู่นาน กว่าจะทำได้ แล้วก็ได้ออกมาแบบนี้


data Tree  a = Node a (Maybe (Tree a)) (Maybe (Tree a))
                deriving (Show)

ถ้าแบบไม่ใช้ Maybe ตามตัวอย่างในหนังสือจะเป็นแบบนี้ ซึ่งจะมี variable constructor 2 ตัวโดย มี Empty อีกตัว


data Tree  a = Node a (Tree a) (Tree a)
                      | Empty
                deriving (Show)

data type Tree ที่สร้างมาเป็น type แบบ Recursive types จะเห็นว่า pattern ของ variable constructor จะมี
data type Tree อยู่ด้วย ตัวอย่างการเอาไปใช้งานแบบ ไม่ใช้ Maybe จะเป็นแบบนี้


myTree = Node 10 Empty Empty
myTree2 = Node 10 (Node 20 Empty Empty) Empty

ส่วนแบบ Maybe เราไม่จำเป็นต้อง สร้าง Empty ขึ้นมาเพราะเราจะใช้ Nothing ซึ่งเป็น ข้อมูลแบบ Maybe ในการกำหนดค่า
childNode ของ Tree ได้ เช่น


myTree = Node 10 Nothing Nothing

และ ใช้ Just ในการกำหนด childNode ที่ไม่เป็น Nothing


myTree2 = Node 10 (Just (Node 20 Nothing Nothing)) Nothing

จบแค่นี้ครับ ไม่ได้อัพบล็อคตัวเองซะนาน เพราะหัวข้ออื่นๆก็เอาไปอัพที่ *66.com ซะหมดแล้ว

Comments (2) »

Coldfusion cfloop readline from file

ตอนแรกตั้งใจอ่านไฟล์ โดยใช้ cffile ปกติ แล้วค่อยมาวนลูปค่าในไฟล์ที่ละบรรทัด
แล้วค้นไปเจอว่า CF8 มันสามารถใช้ cfloop กับ file ได้เลยลองใช้ดู ง่ายดีจริงๆ
ตัวอย่างเช่น


<cfloop file="#Expandpath('nqi/cfcservice/')#data.txt" index="line">
    <cfscript>
        data = listtoarray(line,"|");
    </cfscript>
    <cfquery datasource="AisNQG">
        insert into nqi_presentation values
        (<cfqueryparam cfsqltype="cf_sql_date" value="#data[1]#">,
         <cfqueryparam cfsqltype="cf_sql_varchar" value="#data[2]#">,
         <cfqueryparam cfsqltype="cf_sql_varchar" value="#data[3]#">,
         <cfqueryparam cfsqltype="cf_sql_varchar" value="#data[4]#">,
         <cfqueryparam cfsqltype="cf_sql_varchar" value="#data[5]#">,
         <cfqueryparam cfsqltype="cf_sql_varchar" value="#data[6]#">,
         <cfqueryparam cfsqltype="cf_sql_numeric" value="#data[7]#">,
         <cfqueryparam cfsqltype="cf_sql_numeric" value="#data[8]#">
         )
    </cfquery>
</cfloop>

แค่ใส่ attribute file เป็นพาธของไฟล์ ที่จะอ่าน แล้ว ใส่ตัวแปรให้กับ attribute index 
โดย เช่น line โดยตัวแปรนี้จะเก็บข้อมูลของแต่ละบรรทัดในไฟล์ที่กำลังอ่าน

Leave a comment »

Simple List Functions

ส่วนใหญ่แล้วการคำนวณต่างๆใน haskell programs คือการประมวลผล list ซึ่งมี 3 ฟังก์ชันหลักที่ทำหน้าที่ประมวลผลเกี่ยวกับ list คือ map, filter, foldr(รวมทั้ง foldl ด้วย)

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

Read the rest of this entry »

Leave a comment »

Strings in Haskell

String ใน haskell ก็คือ list ของข้อมูลแบบ Chars นั่นเอง ดังนั้นเราจึงสามารถสร้าง string อย่างเช่น “hello” ได้แบบนี้

Prelude> ‘H’:'e’:'l’:'l’:'o’:[]
“Hello”

List สามารถเชื่อมต่อกันได้ด้วย ++ string ก็ได้เช่นเดียวกันเพราะว่า string ก็คือ list ตัวอย่างเช่น

Read the rest of this entry »

Leave a comment »

Lists

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

Prelude> [1,2]
[1,2]
Prelude> [1,2,3]
[1,2,3]

Read the rest of this entry »

Leave a comment »

Pairs, Triples, … Tuples

รูปแบบข้อมูลใน haskell นอกจากจะมาเป็นแบบค่าเดี่ยวๆแล้ว ยังมีข้อมูลแบบ pair ซึ่งก็คือข้อมูลแบบเป็นคู่ๆ เช่นข้อมูล pair ของจำนวนเต็ม สามารถสร้างได้โดยนำค่าใส่ใน วงเล็บ โดยมีคอมม่าคั่นข้อมูลคู่นั้น ลองใช้ pair ดูผ่าน ghci
Prelude> (4,9)
(4,9)
นี่คือ pair ของเลข 4 และ 9 ใน haskell ค่าที่นำมาเป็นคู่ข้อมูล ไม่จำเป็นต้องเป็นชนิดข้อมูลแบบเดียวกัน เราสามารถสร้าง pair ของเลขจำนวนเต็ม คู่กับ string ได้ ซึ่งจะต่างกับ list ที่จำเป็นต้องมีข้อมูลชนิดเดียวกันทั้งหมด
มี ฟังก์ชัน 2 ฟังก์ชันที่ใช้สำหรับดึงค่า ข้อมูลตัวแรกของ pair และ ข้อมูลตัวที่สองของ pair นั่นคือ fst และ snd ตัวอย่างการใช้งานดังนี้

Read the rest of this entry »

Leave a comment »

Exercise 3.10

วันนี้ลองทำแบบฝึกหัดที่ 3.10 ใน Yet Another Haskell Tutorial ดู โจทย์มีอยูว่า

Exercise 3.10 Write a program that will repeatedly ask the user for numbers until she
types in zero, at which point it will tell her the sum of all the numbers, the product of
all the numbers, and, for each number, its factorial. For instance, a session might look
like:

Read the rest of this entry »

Leave a comment »

แก้ปัญหา หอคอย ฮานอย (Tower of Hanoi) กัน

วันนี้จะมาเขียนโปรแกรมแก้ปัญหา Tower of Hanoi กัน ปัญหานี้มีอยู่ว่า มีเสา 3 เสา แล้วในนั้นมันจะมีแผ่น disk อยู่ที่เสา โดยที่แผ่นใหญ่ต้องอยู่ด่านล่างของแผ่นเล็กเสมอ โดยปัญหาก็คือเราจะย้าย disk ทั้งหมดจากอีกเสา ไปอีกเสา ได้อย่างไร และ ทำด้วยจำนวนวิธีที่จำนวนการย้ายน้อยที่สุด

Tower of Hanoi

Read the rest of this entry »

Comments (2) »