Friday, May 05, 2006
อยากดู
หนังเรื่องนี้จะหลุดเข้ามาเมืองไทยเหลือเปล่านี่
SKETCHES OF FRANK GEHRY
น่าดูมาก
ผมชอบดูพวกสารดคีที่แสดง process การสร้างสรรค์
ที่เคยดูแล้วชอบก็มี
สารดดี I.M. Pei ที่เอามาออกในช่อง discovery ของ cable TV.
ได้มีโอกาสชม Lourve แบบไม่ต้องบินไปปารีส
อีกเรื่องก็คือสารดดี แสดง process การวาดรูปของ picasso
เลยรู้ว่ารูปหนึ่งๆของ picaasso ก่อนจะออกมาได้นั้น
ผ่านการเขียนทับหรือ transform เยอะมาก
Related link from Roti
Server Push
ช่วงนี้กำลังหา solution เพื่อที่จะทำ Server Push อยู่
โจทย์ตั้งไว้ว่า user จะใช้ browser ในการ monitor เหตุการณ์
ซึ่งต้องการ respone time ที่เร็วพอสมควร
วิธี polling, refresh browser ทุก x วินาที นี่ตัดทิ้งไปก่อนเลย
คราวนี้ก็เลยต้องชั่งน้ำหนักอยู่ว่าจะใช้วิธีไหนดี
วิธีที่ implement ได้ทันทีเลย ก็คือใช้พวก Applet
เปิด socket ไปยัง server
ถ้าให้หรูหน่อย ก็ใช้ applet ต่อเป็น JMS Client
ง่ายขึ้นอีกหน่อย ก็ใช้ Jabber protocol
แต่ผมดันเกิดอยากลองใช้ javascript client ล้วนๆดูบ้าง
ก็เลยต้องลำบากเพิ่มขึ้นหน่อย
เริ่มด้วยวิธี primitive สุด ก็คือ เมื่อ browser
request มาขอข้อมูลแล้ว เมื่อส่งข้อมูลเสร็จ แทนที่ server จะสั่งปิด connection เลย
ก็ให้ server วน loop รอ
เมื่อไรที่เกิด event ที่ server, ก็ค่อย write stream สั่ง flush
จากนั้นก็เข้า loop wait รอต่อไป
โดยวิธีนี้ implement ได้ 2 วิธี ก็คือ
implement ตรงๆ ตอน browser get เลย
กับอีกวิธีหนึ่งก็เอาไปฝากผ่านทาง iframe
แต่ไม่ว่าใช้ทางใด ข้อเสียที่เห็นได้ชัดก็คือ
browser จะแสดง icon หมุนๆๆๆ แสดง status ว่ายังได้รับข้อมูลจาก server ไม่หมด
ซึ่งการแสดง status อย่างนี้ น่าจะสร้างความสับสนให้ user
วิธีถัดไปก็คือให้ XMLHttpRequest
แน่นอนว่าช่วยแก้ปัญหา icon หมุนๆๆๆ ได้
แต่ประเด็นปัญหาของวิธีนี้ ก็คือ จะต้องหาทางทำให้ XMLHttpRequest
รับ response เป็นส่วนๆ(chunk) ให้ได้
ซึ่งในกรณีของ Firefox เราสามารถใช้ multipart/x-mixed-replace
เข้ามาช่วยได้
แน่นอนว่าวิธีนี้ IE ไม่ support
แต่ใน IE ก็มี component หนึ่งที่ช่วย support วิธีนี้เหมือนกัน
เรียกว่า ondataavailable - MSXML 4.0
ดูแล้วถ้าต้องทำให้ support หลายๆ browser
วิธี chunk ก็ดูเป็นการทรมานจิตใจเกินไป
เมื่อ chunk ไม่ได้ ก็เลยมีคนคิดวิธีว่า
ก็ให้เปิด XMLHttpRequest ไปที่ server
โดยกรณีที่ server มี event ที่จะ push อยู่แล้วก็จะตอบกลับมาเลย
แต่ถ้ายังไม่มี server ก็จะ loop รอก่อน
ถ้าครบเวลาที่กำหนดแล้วยังไม่มี event มา
server ก็จะ return กลับมา
ในส่วนของ client เมื่อได้รับ return message จาก server (ไม่ว่าจะมี event หรือไม่มี event มา)
client ก็จะ request เปิด XMLHttpRequest ซ้ำกลับไปอีกทันที
เนื่องจาก request เกิดอย่างต่อเนื่อง
socket connection ก็เลยถูกเปิดแช่ไว้ เป็น persistent connection
บางคนเรียกวิธีนี้ว่า waiting poll mechanism
วิธีนี้ ค่อนข้างมีคนนิยมกันมาก ไม่ว่าจะเป็นใน
DWR 2.0, ActiveMQ Ajax, ฯลฯ
วิธีถัดไปก็คือ ใช้ AFLAX
วิธีนี้แอบใช้ feature ใน Flash 8
มีข้อเสียนิดหน่อยตรงที่
browser ต้อง install flash 8 ด้วย
กับเอกสารที่อธิบายน้อยไปหน่อย
ตอนนี้ทดลองทดสอบ ไป 2 วิธีแล้ว
ก็คือ primitive กับ DWR
ส่วน multipart ยังติดปัญหาที่ servlet มัน overwrite content-type ที่ผม set ไว้
ก็เลยขี้เกียจดูต่อ
เหลือวิธี aflax กับ ActiveMQ Ajax ที่จะลองทำพรุ่งนี้
โจทย์ตั้งไว้ว่า user จะใช้ browser ในการ monitor เหตุการณ์
ซึ่งต้องการ respone time ที่เร็วพอสมควร
วิธี polling, refresh browser ทุก x วินาที นี่ตัดทิ้งไปก่อนเลย
คราวนี้ก็เลยต้องชั่งน้ำหนักอยู่ว่าจะใช้วิธีไหนดี
วิธีที่ implement ได้ทันทีเลย ก็คือใช้พวก Applet
เปิด socket ไปยัง server
ถ้าให้หรูหน่อย ก็ใช้ applet ต่อเป็น JMS Client
ง่ายขึ้นอีกหน่อย ก็ใช้ Jabber protocol
แต่ผมดันเกิดอยากลองใช้ javascript client ล้วนๆดูบ้าง
ก็เลยต้องลำบากเพิ่มขึ้นหน่อย
เริ่มด้วยวิธี primitive สุด ก็คือ เมื่อ browser
request มาขอข้อมูลแล้ว เมื่อส่งข้อมูลเสร็จ แทนที่ server จะสั่งปิด connection เลย
ก็ให้ server วน loop รอ
เมื่อไรที่เกิด event ที่ server, ก็ค่อย write stream สั่ง flush
จากนั้นก็เข้า loop wait รอต่อไป
โดยวิธีนี้ implement ได้ 2 วิธี ก็คือ
implement ตรงๆ ตอน browser get เลย
กับอีกวิธีหนึ่งก็เอาไปฝากผ่านทาง iframe
แต่ไม่ว่าใช้ทางใด ข้อเสียที่เห็นได้ชัดก็คือ
browser จะแสดง icon หมุนๆๆๆ แสดง status ว่ายังได้รับข้อมูลจาก server ไม่หมด
ซึ่งการแสดง status อย่างนี้ น่าจะสร้างความสับสนให้ user
วิธีถัดไปก็คือให้ XMLHttpRequest
แน่นอนว่าช่วยแก้ปัญหา icon หมุนๆๆๆ ได้
แต่ประเด็นปัญหาของวิธีนี้ ก็คือ จะต้องหาทางทำให้ XMLHttpRequest
รับ response เป็นส่วนๆ(chunk) ให้ได้
ซึ่งในกรณีของ Firefox เราสามารถใช้ multipart/x-mixed-replace
เข้ามาช่วยได้
แน่นอนว่าวิธีนี้ IE ไม่ support
แต่ใน IE ก็มี component หนึ่งที่ช่วย support วิธีนี้เหมือนกัน
เรียกว่า ondataavailable - MSXML 4.0
ดูแล้วถ้าต้องทำให้ support หลายๆ browser
วิธี chunk ก็ดูเป็นการทรมานจิตใจเกินไป
เมื่อ chunk ไม่ได้ ก็เลยมีคนคิดวิธีว่า
ก็ให้เปิด XMLHttpRequest ไปที่ server
โดยกรณีที่ server มี event ที่จะ push อยู่แล้วก็จะตอบกลับมาเลย
แต่ถ้ายังไม่มี server ก็จะ loop รอก่อน
ถ้าครบเวลาที่กำหนดแล้วยังไม่มี event มา
server ก็จะ return กลับมา
ในส่วนของ client เมื่อได้รับ return message จาก server (ไม่ว่าจะมี event หรือไม่มี event มา)
client ก็จะ request เปิด XMLHttpRequest ซ้ำกลับไปอีกทันที
เนื่องจาก request เกิดอย่างต่อเนื่อง
socket connection ก็เลยถูกเปิดแช่ไว้ เป็น persistent connection
บางคนเรียกวิธีนี้ว่า waiting poll mechanism
วิธีนี้ ค่อนข้างมีคนนิยมกันมาก ไม่ว่าจะเป็นใน
DWR 2.0, ActiveMQ Ajax, ฯลฯ
วิธีถัดไปก็คือ ใช้ AFLAX
วิธีนี้แอบใช้ feature ใน Flash 8
มีข้อเสียนิดหน่อยตรงที่
browser ต้อง install flash 8 ด้วย
กับเอกสารที่อธิบายน้อยไปหน่อย
ตอนนี้ทดลองทดสอบ ไป 2 วิธีแล้ว
ก็คือ primitive กับ DWR
ส่วน multipart ยังติดปัญหาที่ servlet มัน overwrite content-type ที่ผม set ไว้
ก็เลยขี้เกียจดูต่อ
เหลือวิธี aflax กับ ActiveMQ Ajax ที่จะลองทำพรุ่งนี้
Related link from Roti
Wednesday, May 03, 2006
CSS Image
ลองเข้าไปดู Link นี้ครับ ProofOfConcept
ดูภายนอกก็ดูปกติดี
ลอง click ขวาเพื่อดู source code สิครับ
อา น่าตื่นเต้นขึ้นมาหน่อย
มี div tag เต็มไปหมดเลย
สังเกตว่า ตำแหน่งว่า ขยับไปทีละ 3 pixel
ที่นี้ลองเปิดดู css ที่แนบมา
div มีขนาด 3x1 pixel และมีการกำหนด สีให้กับแต่ละ pixel
รวมๆกันแล้ว มันก็คือ รูปที่เขียนขึ้นโดยใช้ CSS เพียวๆ
(ไม่ได้ใช้ background image)
อ่านเนื้อหาเต็มๆได้ที่นี่ครับ
แล้วก็มีคนนำไปต่อยอดเป็น CSS Font แล้วครับ
ดูได้ที่นี่ A CSS Font
ดูภายนอกก็ดูปกติดี
ลอง click ขวาเพื่อดู source code สิครับ
อา น่าตื่นเต้นขึ้นมาหน่อย
มี div tag เต็มไปหมดเลย
<div style="top: 0pt; left: 0pt;" class="c0"> </div>
<div style="top: 0pt; left: 3px;" class="c1"> </div>
<div style="top: 0pt; left: 6px;" class="c1"> </div>
...
สังเกตว่า ตำแหน่งว่า ขยับไปทีละ 3 pixel
ที่นี้ลองเปิดดู css ที่แนบมา
.c0 {
border-left:1px solid #CCCC99;
background:#CCCC99;
border-right:1px solid #CCCC99;
}
.c1 {
border-left:1px solid #CCCC99;
background:#CCCC99;
border-right:1px solid #CCCC99;
}
.c2{
border-left:1px solid #CCCC99;
background:#BEBE8F;
border-right:1px solid #363629;
}
div มีขนาด 3x1 pixel และมีการกำหนด สีให้กับแต่ละ pixel
รวมๆกันแล้ว มันก็คือ รูปที่เขียนขึ้นโดยใช้ CSS เพียวๆ
(ไม่ได้ใช้ background image)
อ่านเนื้อหาเต็มๆได้ที่นี่ครับ
แล้วก็มีคนนำไปต่อยอดเป็น CSS Font แล้วครับ
ดูได้ที่นี่ A CSS Font
Related link from Roti
Links - Programming Language for Web application
เมื่อวันก่อนอ่านเจอ paper Links
คำอธิบายย่อๆ ก็คือ
Link คือ Programming Language ที่ออกแบบมาสำหรับการเขียน Web application
โดยเขามองว่า เดิมที่เราเขียน web application นั้น
เราต้องใช้อย่างน้อย 3 ภาษา ก็คือ sql สำหรับ access database
, javascript + HTML สำหรับส่วน UI
สุดท้ายก็ programming language สำหรับส่วน
business logic ซึ่งอาจจะเป็น c, java, python ฯลฯ
ซึ่งคนที่จะเขียน Web Application ต้องใช้เวลาในการเรียนรู้ทั้ง 3 ส่วน
และยังเกิดปัญหาที่เรียกว่า impedance mismatch
(ข้อมูลจาก sql แปลงให้อยู่ในรูป object เพื่อให้เหมาะกับ java
จากนั้นเมื่อจะ render ก็แปลงกลับมาอยู่ในรูปตาราง html )
Links ก็เลยเกิดมา เพื่อเป็น unify language สำหรับ
การเขียน Web application
ลองดูตัวอย่าง program เขาดู จะได้เห็นภาพ
การทำงานของโปรแกรมนี้ ก็คือ
เริ่มต้นมันจะแสดง form ให้เราใส่ตัวเลขที่ต้องการ
เมื่อสั่ง submit ก็จะแสดงผลเป็นตาราง factorial ตามจำนวนที่เราใส่
จะเห็นว่า ตัวภาษามีลักษณะเป็น functional language
และ function แต่ละ function จะต้องกำหนดว่า
run อยู่บน client หรือ run บน server
ประเด็นที่น่าสนใจ ก็คือ
ทดลอง run demo ของ Links ได้ที่นี่ Links demos
คำอธิบายย่อๆ ก็คือ
Link คือ Programming Language ที่ออกแบบมาสำหรับการเขียน Web application
โดยเขามองว่า เดิมที่เราเขียน web application นั้น
เราต้องใช้อย่างน้อย 3 ภาษา ก็คือ sql สำหรับ access database
, javascript + HTML สำหรับส่วน UI
สุดท้ายก็ programming language สำหรับส่วน
business logic ซึ่งอาจจะเป็น c, java, python ฯลฯ
ซึ่งคนที่จะเขียน Web Application ต้องใช้เวลาในการเรียนรู้ทั้ง 3 ส่วน
และยังเกิดปัญหาที่เรียกว่า impedance mismatch
(ข้อมูลจาก sql แปลงให้อยู่ในรูป object เพื่อให้เหมาะกับ java
จากนั้นเมื่อจะ render ก็แปลงกลับมาอยู่ในรูปตาราง html )
Links ก็เลยเกิดมา เพื่อเป็น unify language สำหรับ
การเขียน Web application
ลองดูตัวอย่าง program เขาดู จะได้เห็นภาพ
การทำงานของโปรแกรมนี้ ก็คือ
เริ่มต้นมันจะแสดง form ให้เราใส่ตัวเลขที่ต้องการ
เมื่อสั่ง submit ก็จะแสดงผลเป็นตาราง factorial ตามจำนวนที่เราใส่
fun request(s) client {
dom!Document(
<html>
<body>
<h1>Please type a number</h1>
<form l:onsubmit="{response(t)}" l:onkeyup="{request(t)}">
<input type="text" value="{s}" l:name="t"/>
{
if (is_integer(s))
<input type="submit"/>
else
<input type="submit" disabled="disabled"/>
}
</form>
</body>
</html>
)
}
fun response(s) client {
var n = int_of_string(s);
dom!Document(
<html>
<body>
<h1>Factorials up to {enxml(string_of_int(n))}</h1>
<table>{
for ((i,f) <- factorialsUpto(n))
<tr>
<td>{enxml(string_of_int(i))}</td>
<td>{enxml(string_of_int(f))}</td>
</tr>
}</table>
</body>
</html>
)
}
fun factorialsUpto(n) server {
for (row <- Table "factorials"
with { i : Int, f : Int }
order [i : asc]
from database "postgresql:factorials::5432:www-data:")
where (row.i <= n)
[(row.i,row.f)]
}
request("")
จะเห็นว่า ตัวภาษามีลักษณะเป็น functional language
และ function แต่ละ function จะต้องกำหนดว่า
run อยู่บน client หรือ run บน server
ประเด็นที่น่าสนใจ ก็คือ
- จะเห็นว่า function สามารถ call ข้าม space กันได้ (client -> server)
โดย technique ที่เขาใช้ implement สำหรับการ call แบบนี้ก็คือ
XMLHttpRequest (Ajax) - html integrate เข้าเป็นเนื้อเดียวกับ language
- Style โปรแกรมมีลักษณะเป็น Continuations
(ผมกำลังหัดเขียน Web Application ด้วย PLT Scheme อยู่
style การเขียนเหมือนกันมากเลย)
ทดลอง run demo ของ Links ได้ที่นี่ Links demos
Related link from Roti
Rails - Project แรก
ที่บริษัทฯผม มีนโยบายไม่รับงานเล็ก (หยิ่งจริงๆ)
เดือนร้อนถึงผมที่อยากจะทดสอบ Rails
ไม่สามารถหา project จริงๆมาลองได้
โชคดีที่บริษัทน้องชาย(สถาปนิก) กำลังขยายงานจากงาน design
(SIPA ของ mk ก็ใช้บริการเหมือนกันนะ)
ออกไปทำงานด้าน web design
แล้วบังเอิญได้งานที่ค่อนข้าง dynamic มา
ผมก็เลยโชคดีได้เหยื่อผู้โชคร้าย
(ส่วนน้องชายเข็ดไปแล้ว เจอค่าตัว programmer เข้าไป)
ผลลัพท์ที่ได้จากการทดสอบ ก็คือ
rails ทำให้งาน web ที่น่าเบื่อ สนุกขึ้นมาได้
(งานนี้ ถ้าให้เขียนด้วย php หรือ java นี่ คงต้องขอคิดดูก่อน)
ส่วนเวลาที่ใช้ coding ก็ประมาณอาทิตย์ละ 1 วัน
ทั้งหมด 4 อาทิตย์
ถ้าเป็นเรื่อง logic นี่ไม่ถึงวันก็เสร็จ
แต่ที่ใช้เวลานาน ก็มีอยู่ 2 เรื่อง
อันนี้คือ สถิติของ project นี้
code 1000 กว่าบรรทัดนี่ เป็น generate code ซะไม่รู้เท่าไร
น่าจะเกิน 80% นะ
ตอนนี้ก็เหลือแต่ deploy ขึ้น host จริง
ซึ่งต้องไปวัดดวงว่า จะเจอ Host ดีหรือไม่ดี
เดือนร้อนถึงผมที่อยากจะทดสอบ Rails
ไม่สามารถหา project จริงๆมาลองได้
โชคดีที่บริษัทน้องชาย(สถาปนิก) กำลังขยายงานจากงาน design
(SIPA ของ mk ก็ใช้บริการเหมือนกันนะ)
ออกไปทำงานด้าน web design
แล้วบังเอิญได้งานที่ค่อนข้าง dynamic มา
ผมก็เลยโชคดีได้เหยื่อผู้โชคร้าย
(ส่วนน้องชายเข็ดไปแล้ว เจอค่าตัว programmer เข้าไป)
ผลลัพท์ที่ได้จากการทดสอบ ก็คือ
rails ทำให้งาน web ที่น่าเบื่อ สนุกขึ้นมาได้
(งานนี้ ถ้าให้เขียนด้วย php หรือ java นี่ คงต้องขอคิดดูก่อน)
ส่วนเวลาที่ใช้ coding ก็ประมาณอาทิตย์ละ 1 วัน
ทั้งหมด 4 อาทิตย์
ถ้าเป็นเรื่อง logic นี่ไม่ถึงวันก็เสร็จ
แต่ที่ใช้เวลานาน ก็มีอยู่ 2 เรื่อง
- เรื่องความสวยงาม
code ที่ได้จาก designer อยู่ในรูป table layout
ก็พยายามเปลี่ยนบางส่วนให้เป็น CSS แทน - นั่งทดลองทำวิธีต่างๆ
เนื่องจากเป็น project เล็ก
ก็เลยทำให้ refactor หรือเปลี่ยนวิธี implement ได้ง่ายๆ
อันนี้คือ สถิติของ project นี้
code 1000 กว่าบรรทัดนี่ เป็น generate code ซะไม่รู้เท่าไร
น่าจะเกิน 80% นะ
ตอนนี้ก็เหลือแต่ deploy ขึ้น host จริง
ซึ่งต้องไปวัดดวงว่า จะเจอ Host ดีหรือไม่ดี
Related link from Roti
Tuesday, May 02, 2006
รำลึกความหลัง
ไปเจอรูปสวยๆใน สิมิลัน รำลึก
ก็เลยเกิดภาวะย้อนอดีต
ความหลังๆหลายๆอย่างของผมเกิดขึ้นที่นี่แหล่ะ
ยังจำ การดำน้ำครั้งแรกที่สิมิลัน ได้
เขาปล่อยให้ดำหน้าเกาะ 4 เพื่อให้ซ้อมความคุ้นเคยก่อน
กำหนดความลึกไม่เกิน 30 feet
ผมกับ buddy ผู้อ่อนต่อโลก
อ่านเข็มความลึก ไม่เกิน 30 เหมือนกัน
แต่เป็น 30 metre
ดีนะที่รู้สึกว่ามันลึก เลยอยู่แถว 25 metre
แต่ก็คุ้ม เพราะได้พบเจอกระเบนยักษ์
ที่สิมิลัน ก็เป็นที่ที่ทำให้ผม รู้จัก limit การว่ายน้ำของตัวเองด้วย
วันหนึ่ง ระหว่างจอดพักกลางวัน, พี่มณู ชวนน้องๆว่ายน้ำรอบเกาะเล่นกัน
เกาะนี้เป็นเกาะเล็กๆที่อยู่ข้างเกาะ 4 (ไม่รู้ใช่เกาะ 5 หรือเปล่า)
ดูด้วยสายตา เดินรอบๆก็ใช้เวลาไม่นานหรอก
ก็เลยเอาแค่แว่นว่ายน้ำไปอันเดียว
ตืนกบไม่ได้ใช้
กลับมาขึ้นเรืออีกที ถึงรู้ว่าใช้เวลาว่ายไป 2 ชั่วโมง
ที่นี่อีกเช่นกัน ที่ทำให้ผมรู้จัดการดำน้ำกลางคืน แบบไม่ใช้ไฟฉาย
ในคืนวันที่พระจันทร์เต็มดวง แสงจันทร์จะสว่างพอ
ที่เราจะมองเห็นเงาตะคุ่มๆใต้น้ำได้
บรรยากาศนี่บรรยายไม่ถูกเลย
มันกึ่งจริงกึ่งฝันอย่างไรไม่รู้
เนื่องจากไม่มีท่าเทียบเรือ
การเดินทางขึ้นลงเกาะ ต้องใช้เรือเล็กเข้ามาช่วย
แต่ผมมักนิยมใช้วิธีว่ายน้ำเอาเสียมากกว่า
ซึ่งข้อเสียก็คือ
ถ้าคนบนเรือกำลังทำทุกข์หนัก ตอนที่เราว่ายเข้าไปพอดี
เราอาจโชคร้ายว่ายฝ่าดงอึก็ได้
ก็เลยเกิดภาวะย้อนอดีต
ความหลังๆหลายๆอย่างของผมเกิดขึ้นที่นี่แหล่ะ
ยังจำ การดำน้ำครั้งแรกที่สิมิลัน ได้
เขาปล่อยให้ดำหน้าเกาะ 4 เพื่อให้ซ้อมความคุ้นเคยก่อน
กำหนดความลึกไม่เกิน 30 feet
ผมกับ buddy ผู้อ่อนต่อโลก
อ่านเข็มความลึก ไม่เกิน 30 เหมือนกัน
แต่เป็น 30 metre
ดีนะที่รู้สึกว่ามันลึก เลยอยู่แถว 25 metre
แต่ก็คุ้ม เพราะได้พบเจอกระเบนยักษ์
ที่สิมิลัน ก็เป็นที่ที่ทำให้ผม รู้จัก limit การว่ายน้ำของตัวเองด้วย
วันหนึ่ง ระหว่างจอดพักกลางวัน, พี่มณู ชวนน้องๆว่ายน้ำรอบเกาะเล่นกัน
เกาะนี้เป็นเกาะเล็กๆที่อยู่ข้างเกาะ 4 (ไม่รู้ใช่เกาะ 5 หรือเปล่า)
ดูด้วยสายตา เดินรอบๆก็ใช้เวลาไม่นานหรอก
ก็เลยเอาแค่แว่นว่ายน้ำไปอันเดียว
ตืนกบไม่ได้ใช้
กลับมาขึ้นเรืออีกที ถึงรู้ว่าใช้เวลาว่ายไป 2 ชั่วโมง
ที่นี่อีกเช่นกัน ที่ทำให้ผมรู้จัดการดำน้ำกลางคืน แบบไม่ใช้ไฟฉาย
ในคืนวันที่พระจันทร์เต็มดวง แสงจันทร์จะสว่างพอ
ที่เราจะมองเห็นเงาตะคุ่มๆใต้น้ำได้
บรรยากาศนี่บรรยายไม่ถูกเลย
มันกึ่งจริงกึ่งฝันอย่างไรไม่รู้
เนื่องจากไม่มีท่าเทียบเรือ
การเดินทางขึ้นลงเกาะ ต้องใช้เรือเล็กเข้ามาช่วย
แต่ผมมักนิยมใช้วิธีว่ายน้ำเอาเสียมากกว่า
ซึ่งข้อเสียก็คือ
ถ้าคนบนเรือกำลังทำทุกข์หนัก ตอนที่เราว่ายเข้าไปพอดี
เราอาจโชคร้ายว่ายฝ่าดงอึก็ได้
Related link from Roti
Sunday, April 30, 2006
[Lisp] car, cdr, cons
car, cdr, cons เป็นคำสั่งพื้นฐานใน Lisp
เริ่มที่ cons ก่อน
cons จะทำหน้าที่สร้าง pair ขึ้นมา
ตัวอย่าง
ที่สนุกก็คือ list ก็คือ pair แบบหนึ่ง
ส่วน car ใช้สำหรับ extract element แรกใน pair
กลับกัน cdr ใช้สำหรับ extract element ที่สอง
แต่ที่น่าสนใจคืออันนี้
(ไปเจอใน blog ของ archie maskill
เรื่อง Blurring the Line Between Data and Procedures
)
คำถาม ก็คือ ถ้าเราจะ implement cons, car, cdr ด้วย ภาษา lisp เอง
เราจะเขียนมันอย่างไร
(ตัวอย่างนี้ใช้ dialect scheme)
ดู code แล้ว คนที่ไม่คุ้นกับ functional language ก็จะเริ่มงงนิดๆ
ตรงที่การเรียกใช้
ส่วน car กับ cde ก็เป็นการเรียกใช้ lambda นั้นๆ
แต่ที่ดูแล้ว ต้องปรับตาปรับใจนานหน่อย ก็ต้องแบบนี้
ถ้าค่อยๆ ดู ก็จะเห็นว่า cons return เป็น function ที่รอรับ parameter เป็น function
จากนั้นการเรียกใช้ car ก็คือการ call function ที่ได้จาก cons ด้วย function
เริ่มที่ cons ก่อน
cons จะทำหน้าที่สร้าง pair ขึ้นมา
ตัวอย่าง
(cons 1 2) ;; => (1 . 2)
ที่สนุกก็คือ list ก็คือ pair แบบหนึ่ง
(1 2) จริงแล้ว ก็คือ (1 . (2 . nil))
(1 2 3) ก็คือ (1 . (2 . (3 . nil)))
ส่วน car ใช้สำหรับ extract element แรกใน pair
(car (cons 1 2)) ;; => 1
กลับกัน cdr ใช้สำหรับ extract element ที่สอง
(cdr (cons 1 2)) ;; => 2
แต่ที่น่าสนใจคืออันนี้
(ไปเจอใน blog ของ archie maskill
เรื่อง Blurring the Line Between Data and Procedures
)
คำถาม ก็คือ ถ้าเราจะ implement cons, car, cdr ด้วย ภาษา lisp เอง
เราจะเขียนมันอย่างไร
(ตัวอย่างนี้ใช้ dialect scheme)
(define (cons a b)
(lambda (pick)
(cond ((= pick 1) a)
((= pick 2) b))))
(define (car x) (x 1))
(define (cdr x) (x 2))
ดู code แล้ว คนที่ไม่คุ้นกับ functional language ก็จะเริ่มงงนิดๆ
ตรงที่การเรียกใช้
cons a b
จะได้ function กลับมาส่วน car กับ cde ก็เป็นการเรียกใช้ lambda นั้นๆ
แต่ที่ดูแล้ว ต้องปรับตาปรับใจนานหน่อย ก็ต้องแบบนี้
(define (cons x y)
(lambda (m) (m x y)))
(define (car z)
(z (lambda (p q) p)))
ถ้าค่อยๆ ดู ก็จะเห็นว่า cons return เป็น function ที่รอรับ parameter เป็น function
จากนั้นการเรียกใช้ car ก็คือการ call function ที่ได้จาก cons ด้วย function
(lambda (p q) p)
Related link from Roti
เมื่อ Rails พบ Asterisk
Ruby Asterisk Gateway Interface (RAGI)
คือ Library ที่ทำให้ Ruby code สามารถทำงานร่วมกับ Asterisk server ได้
ซึ่งแน่นอนว่า เมื่อ ruby คุยกับ Asterisk ได้
rails ก็ย่อยได้อานิสงค์ไปด้วย
RAGI เป็น opensource ของ SNAPVINE, Inc
มี license เป็น BSD
Tutorial ของ RAGI เขาทดลองทำ Application ที่ใช้ track UPS package
ที่มี use case อย่างนี้ดู
ลองดูตัวอย่าง code ในส่วนของ rails ที่ทำหน้าที่ตอบรับโทรศัพท์
อ่านเพิ่มเติม
คือ Library ที่ทำให้ Ruby code สามารถทำงานร่วมกับ Asterisk server ได้
ซึ่งแน่นอนว่า เมื่อ ruby คุยกับ Asterisk ได้
rails ก็ย่อยได้อานิสงค์ไปด้วย
RAGI เป็น opensource ของ SNAPVINE, Inc
มี license เป็น BSD
Tutorial ของ RAGI เขาทดลองทำ Application ที่ใช้ track UPS package
ที่มี use case อย่างนี้ดู
- user ลงทะเบียนการใช้งานผ่านทาง web application
- user ระบุ UPS package id ที่ต้องการ track
- หลังจากลงทะเบียนและระบุ package id แล้ว user ก็สามารถ
โทรเข้ามาสอบถาม สถานะของ package ได้
ลองดูตัวอย่าง code ในส่วนของ rails ที่ทำหน้าที่ตอบรับโทรศัพท์
class DeliveryStatusHandler < RAGI::CallHandler
def dialup
answer()
# read the caller id from the connection
user_phone_number = @params[RAGI::CALLERID]
user = User.find_by_phone_number(user_phone_number)
if (user == nil)
speak_text("We could not locate any accounts. Please try again later")
hangUp()
return
end
deliverylist = user.deliveries
speak_text("You have #{deliverylist.size} deliveries to track")
if deliverylist.size > 0
updateAll(deliverylist)
readDeliveryStatus(deliverylist)
else
speak_text("Please go to the website and register some deliveries.")
end
speak_text("Goodbye!")
hangUp()
end
end
อ่านเพิ่มเติม
Related link from Roti
ทำความเข้าใจ Ant Task
Ant เป็นอะไรที่ผมหลีกเลี่ยง ไม่ค่อยอยากเข้าไปทำความรู้จักมากนัก
เวลาจะทำอะไรที ก็เปิดตัวอย่างดูอย่างเดียว จากนั้นก็ เดาๆ มั่วๆไปเรื่อยๆ จนกว่าจะทำงานได้
เมื่อวานมีคนถามเรื่องการใช้งาน war task
กรณีที่มี directory ที่เก็บ lib แยกอยู่หลายที่
จะเขียนอย่างไร
ตัวอย่างโปรเจค structure ของ case นี้ก่อน
ผมก็ใช้วิธีเอาตัวรอดวิธีเดิม มั่วไป 2-3 ที มันก็ work
แต่ระหว่างที่เดินทางกลับบ้าน ก็เกิดอาการปิ๊งขึ้นในหัว
เข้าใจขึ้นมาทันทีว่าอะไรเป็นอะไร ทำไมใส่อย่างนี้ work
ใส่อย่างนี้ไม่ work
วันนี้ก็เลยนั่งดู code ของ Ant เพิ่มเติม
เริ่มที่ hirarchy tree ของ War Class ก่อน
จะเห็นว่า hirarachy tree ยาวเป็นหางว่าวเลย
ตัว Abstract Class
เป็น base task สำหรับ งานที่ต้องการให้สามารถ include, exclude file
โดยใช้ pattern matching ได้
ซึ่งทำให้เราเขียน ant ประมาณนี้ได้
ส่วน
โดยมีการเพิ่ม element ที่ทำให้กำหนด fileset ที่ต้องการได้
รวมทั้งเพิ่ม ZipFileset ที่ extend มาจาก FileSet โดยมี feature ที่ทำให้เรา ระบุ prefix ของ target file ได้
ซึ่งตัวอย่างของการใช้ zip task ใน ant
ซึ่ง
โดยเพิ่ม function ส่วนที่จัดการ Manifest ลงไป
สุดท้าย
โดยเพิ่มส่วน element ที่ช่วยจัดการพวก file ที่อยู่ใน lib, classes, WEB-INF
จริงๆแล้ว features ที่เพิ่มเข้าไปใน war task
มีรากฐานจาก features เดิมใน zip task ทั้งสิ้น
จากตัวอย่างข้างบน
เราสามารถเขียน ในแบบ zip task ได้ดังนี้
(ได้ผลลัพท์เหมือนกัน แต่ editor ที่มี feature dtd-checking
มันจะฟ้องว่าผิด syntax ในส่วนของ file='src/meta..')
ความยากในการทำความเข้าใจ ant ส่วนหนึ่งน่าจะมาจากการที่มันสามารถเขียนได้มากกว่า 1 วิธี
แล้วก็ element อะไรอยู่ใต้ element อะไรได้บ้าง
รวมทั้ง Types ที่มีมากมายให้เลือกใช้
เวลาจะทำอะไรที ก็เปิดตัวอย่างดูอย่างเดียว จากนั้นก็ เดาๆ มั่วๆไปเรื่อยๆ จนกว่าจะทำงานได้
เมื่อวานมีคนถามเรื่องการใช้งาน war task
กรณีที่มี directory ที่เก็บ lib แยกอยู่หลายที่
จะเขียนอย่างไร
ตัวอย่างโปรเจค structure ของ case นี้ก่อน
+ project
+ src
+ bin
+ lib
+ hibernate
+ jdbc
+ doclet
+ dbunit
+ context (www root dir)
ผมก็ใช้วิธีเอาตัวรอดวิธีเดิม มั่วไป 2-3 ที มันก็ work
<war destfile="myapp.war" webxml="src/metadata/myapp.xml">
<fileset dir="context"/>
<lib dir="lib/hibernate">
<lib dir="lib/jdbc">
<classes dir="bin"/>
</war>
แต่ระหว่างที่เดินทางกลับบ้าน ก็เกิดอาการปิ๊งขึ้นในหัว
เข้าใจขึ้นมาทันทีว่าอะไรเป็นอะไร ทำไมใส่อย่างนี้ work
ใส่อย่างนี้ไม่ work
วันนี้ก็เลยนั่งดู code ของ Ant เพิ่มเติม
เริ่มที่ hirarchy tree ของ War Class ก่อน
จะเห็นว่า hirarachy tree ยาวเป็นหางว่าวเลย
ตัว Abstract Class
MatchingTask
เป็น base task สำหรับ งานที่ต้องการให้สามารถ include, exclude file
โดยใช้ pattern matching ได้
ซึ่งทำให้เราเขียน ant ประมาณนี้ได้
<xxx includes="**/*.xx" excludes="yy/zz">
</xxx>
<xxx>
<include name="**/*.html"/>
<exclude name="**/*.page"/>
</xxx>
<xxx>
<and>
<size value="4" units="Ki" when="more"/>
<date datetime="01/01/2001 12:00 AM" when="before"/>
</and>
</xxx>
ส่วน
Zip
รับผิดชอบ logic ในการสร้าง zip fileโดยมีการเพิ่ม element ที่ทำให้กำหนด fileset ที่ต้องการได้
รวมทั้งเพิ่ม ZipFileset ที่ extend มาจาก FileSet โดยมี feature ที่ทำให้เรา ระบุ prefix ของ target file ได้
ซึ่งตัวอย่างของการใช้ zip task ใน ant
<zip destfile="${dist}/manual-and-src.zip">
<fileset dir="${server.src}" casesensitive="yes">
<include name="**/*.java"/>
<exclude name="**/*Test*"/>
</fileset>
<zipfileset dir="htdocs/manual" prefix="docs/user-guide"/>
<zipfileset dir="." includes="ChangeLog27.txt" fullpath="docs/ChangeLog.txt"/>
<zipfileset src="examples.zip" includes="**/*.html" prefix="docs/examples"/>
</zip>
ซึ่ง
Jar
extend Zip
ไปใช้งาน โดยเพิ่ม function ส่วนที่จัดการ Manifest ลงไป
<jar destfile="${dist}/lib/app.jar">
<fileset dir="${build}/classes"
excludes="**/Test.class"
/>
<fileset dir="${src}/resources"/>
<manifest>
<attribute name="Built-By" value="${user.name}"/>
<section name="common/class1.class">
<attribute name="Sealed" value="false"/>
</section>
</manifest>
</jar>
สุดท้าย
War
ก็ extend จาก Jar
อีกทีโดยเพิ่มส่วน element ที่ช่วยจัดการพวก file ที่อยู่ใน lib, classes, WEB-INF
จริงๆแล้ว features ที่เพิ่มเข้าไปใน war task
มีรากฐานจาก features เดิมใน zip task ทั้งสิ้น
จากตัวอย่างข้างบน
<war destfile="myapp.war" webxml="src/metadata/myapp.xml">
<fileset dir="context"/>
<lib dir="lib/hibernate">
<lib dir="lib/jdbc">
<classes dir="bin"/>
</war>
เราสามารถเขียน ในแบบ zip task ได้ดังนี้
(ได้ผลลัพท์เหมือนกัน แต่ editor ที่มี feature dtd-checking
มันจะฟ้องว่าผิด syntax ในส่วนของ file='src/meta..')
<zip destfile="myapp.war">
<zipfileset file="src/metadata/myapp.xml" fullpath="WEB-INF/web.xml"/>
<fileset dir="context"/>
<zipfileset dir="lib/hibernate" prefix="WEB-INF/lib"/>
<zipfileset dir="lib/jdbc" prefix="WEB-INF/lib"/>
<zipfileset dir="bin" prefix="WEB-INF/classes"/>
</zip>
ความยากในการทำความเข้าใจ ant ส่วนหนึ่งน่าจะมาจากการที่มันสามารถเขียนได้มากกว่า 1 วิธี
แล้วก็ element อะไรอยู่ใต้ element อะไรได้บ้าง
รวมทั้ง Types ที่มีมากมายให้เลือกใช้
Related link from Roti
Subscribe to:
Posts (Atom)