Saturday, January 14, 2006

Computer Language

Computer Languages Timeline

พึ่งรู้ว่า
oak ที่เป็นที่มาของ java ได้อิทธิพลบางส่วนจาก scheme
C# ได้อิทธิพลบางส่วนจาก ruby
ruby ได้อิทธิพลบางส่วนจาก python

ส่วนอันนี้
A Chronology of Influential Computer Languages
According to Sammet, over 200 programming languages were developed between 1952 and 1972, but she considered only about 13 of them to be significant.

(มีที่ไม่เคยได้ยินชื่ออยู่เยอะเหมือนกัน)

ถ้ายังไม่สะใจ
ไปนี่เลย
2500 ภาษา

Related link from Roti

Friday, January 13, 2006

Rails Rake Task for Testing Env.

วันนี้นั่ง develop Rails Application
โดยทำตามระเบียบวิธีที่ดี
  • สร้าง table ก็ใช้ Migration
  • แยก database ระหว่าง development, test, production
  • เขียน TestCase ของส่วน Model


พอทำถึงตอน testcase ก็เกิดปัญหาว่า
แล้วเราจะสร้าง table structure ใน test database อย่างไร

ตอนแรกก็นึกถึงคำสั่ง rake migrate ว่ามันจะ
pass parameter อะไรไปได้บ้างหรือเปล่า
แต่หลังจากหาเอกสารใน google แล้ว ก็ไม่พบว่ามี

จากนั้นก็นึกถึง rake db_schema_import
ว่า import ออกมาก่อน แล้วค่อย load กลับเข้าไปใน test

สุดท้ายก็ไปเจอใน source code ใน database.rake ที่อยู่ใต้
/your/gems/path/rails-your-version/lib/tasks

สรุป task ที่เกี่ยวข้องกับเรื่องนี้มี
  • clone_structure_to_test
    Recreate the test databases from the development structure
  • purge_test_database
    Empty the test database
  • load_fixtures
    Load fixtures into the current environment's database

Related link from Roti

Evaluation: moving from Java to Ruby on Rails for the CenterNet rewrite

Related link from Roti

Thursday, January 12, 2006

Dynamic scoping & Static scoping

ลองดูตัวอย่าง ruby อันนี้
def x() 
puts 'outer'
end

def y()
x()
end

def z()
def x
puts 'inner'
end
y()
end

คำถามก็คือ ถ้าเราเรียกใช้งาน method z
เราจะเห็น output ที่ stdio เป็นอะไร ระหว่าง "inner" กับ "outer"

ที่นี้ลองดู javascript บ้าง
function x() {
alert('outer')

}
function y() {
x()
}

function z() {
function x() {
alert('inner')
}
y()
}

ทายสิว่า alert box ที่ได้ จะมีข้อความว่า "inner" หรือ "outer"

ถ้าเป็น scheme หล่ะ
(define (x)
(print "outer"))

(define (y)
(x))

(define (z)
(define (x) print "inner")
(y))


javascript กับ scheme จะได้ message ออกมาเป็น "outer"
ส่วน ruby จะได้คำตอบเป็น "inner"

Static Scope
In a language with static scope, each identifier gets its value from the scope
of its definition, not its use.

Dynamic Scope
In a language with dynamic scope, each identifier gets its value from the
scope of its use, not its definition.


ruby -> dynamic scope
javascript, scheme -> static scope

UPDATE
code ruby เขียนผิด แก้ให้ถูกแล้ว
มันผิดตอนเอาไปทำสวย (syntax highligh)

Related link from Roti

Wednesday, January 11, 2006

ใครมี google earth ลองเปิดไปที่นี่ดู
52 20 10.87N 0 11 43.34W

อย่าลืม zoom เข้าไปดูไกล้ๆหล่ะ
Link

Related link from Roti

Tuesday, January 10, 2006

Haskell quicksort อีกที

post เดิมที่พูดเรื่อง Pure functional programming with Haskell
ลืมลง quote ที่เขาเปรียบเทียบ c code กับ haskell
The C quicksort uses an extremely ingenious technique, invented by Hoare, whereby it sorts the array in place; that is, without using any extra storage. As a result, it runs quickly, and in a small amount of memory. In contrast, the Haskell program allocates quite a lot of extra memory behind the scenes, and runs rather slower than the C program.
In effect, the C quicksort does some very ingenious storage management, trading this algorithmic complexity for a reduction in run-time storage management costs.


เลือก tool ให้เหมาะกับงาน !

Related link from Roti

Pure functional programming with Haskell

เมื่อวันก่อนเห็น quicksort ที่ implement ด้วย Haskell
เห็นแล้วก็อื้งเล็กน้อย
อื้งเพราะอะไรลองติดตามดู
qsort[]     = []
qsort(x:xs) = qsort less ++ [x] ++ qsort more
where less = [y | y <- xs, y < x]
more = [y | y <- xs, y >= x


บรรทัดแรกเป็นการบอกว่า
ถ้ามีคน call qsort โดย pass parameter เป็น empty array
ก็ให้ return ค่า empty array กลับไป

บรรทัดที่ 2 ฝั่งซ้าย บอกว่า
ให้ทำ pattern matching กับ array (parameter) ที่ pass เข้ามา
โดยให้ตัวแรกสุดของ array bound เข้ากับ ตัวแปร x
ส่วนที่เหลือ bound เข้ากับ ตัวแปร xs
สมมติว่า มีการสั่ง qsort [3,5,2,9]
x จะเท่ากับ 3 ส่วน xs จะเท่ากับ [5,2,9]

ส่วนฝั่งขวาของบรรทัดที่ 2 บอกว่า
ผลลัพท์ที่จะ return กลับไป เกิดจาก
การ recursive call qsort ด้วย parameter less
บวกกับ x บวกกับ recursive call qsort ด้วย paramter more
โดย less นั้นได้มาจาก
less = [y | y <- xs, y < x]
(ประโยคนี้ดูแปลกตามากมาก)
การตีความหมายให้เริ่มจาก y <- xs, y < x ก่อน
อันนี้หมายความว่า ให้ y คือ สมาชิกของ set xs โดยที่ค่า y ต้องน้อยกว่า x
less = [y | ...] ก็แปลตรงตัว
less ก็คือ y นั่นเอง โดยที่ datatype ของ y เป็น list (array)

ส่วน more = [y | ... ก็เป็นที่มากกว่าค่า x

เวลาสั่งทำงาน ก็เพียงแต่เรียก
Main> qsort [3,4,1,3,6,45,11,23]
[1,3,3,4,6,11,23,45]


ถ้าเขียนว่าข้างในทำงานอย่างไร ก็คงได้ step ประมาณนี้

qsort [3,4,1,3,6,45,11,23]
= qsort [1] ++ [3] ++ [4,3,6,45,11,23]
= [] ++ [1] ++ [] ++ [3] ++ qsort[3] ++ [4] ++ qsort [6,45,11,23]
.....


ที่บอกว่าอื้ง ก็คือ ทำไมมันช่างเป็นโปรแกรมที่อ่านเข้าใจง่ายเช่นนี้
(เข้าใจง่ายนี่หมายถึงว่า สายตาต้องชินกับการตีความ recursive +
รูัจัก syntax เบื้องต้นก่อนนะ)
ลองเทียบกับ java ดู
static void sort(int a[], int lo0, int hi0) {
int lo = lo0;
int hi = hi0;
if (lo >= hi) {
return;
}
int mid = a[(lo + hi) / 2];
while (lo < hi) {
while (lo<hi && a[lo] < mid) {
lo++;
}
while (lo<hi && a[hi] >= mid) {
hi--;
}
if (lo < hi) {
int T = a[lo];
a[lo] = a[hi];
a[hi] = T;
}
}
if (hi < lo) {
int T = hi;
hi = lo;
lo = T;
}
sort(a, lo0, lo);
sort(a, lo == lo0 ? lo+1 : lo, hi0);
}

(ลอก code มาจาก http://clip.dia.fi.upm.es/Projects/ParForce/Final_review/slides/intro/node4.html )

ปล. มี game ที่เขียนด้วย Haskell ด้วยนะ
ชื่อ game Frag

Related link from Roti

Monday, January 09, 2006

Hibernate StatelessSession

พึ่งรู้ว่าใน Hibernate version 3 มี StatelessSession ให้ใช้

Operations performed via a stateless session bypass Hibernate's event model and interceptors.
...
A stateless session is a lower-level abstraction, much closer to the underlying JDBC.

เหมาะอย่างยิ่งกับ bulk operations

Related link from Roti

Sunday, January 08, 2006

ทดลอง Implement Binary Tree Insert with Oz,Scheme,Ruby

วันนี้นั่งเรียนภาษา Oz
ซึ่งเป็น functional programming ตัวหนึ่ง
เห็นตัวอย่าง function การ insert binary tree
ดูน่าสนใจดี
เพราะ Variable ใน Oz assign ได้ครั้งเดียว
ถ้า assign ซ้ำอีกครั้ง ก็จะเกิด exception

เริ่มที่ definition ก่อน
node ใน binary tree นี้จะประกอบด้วย key กับ value
โดยการจัดเรียบ tree จะใช้วิธีการ compare ค่า key
ถ้าค่า key มีค่าน้อยกว่า ก็จะอยู่ กิ่งซ้าย
ถ้ามากกว่า ก็อยู่ฝั่งขวา



ถ้าเรา insert tree ด้วย key="B" จะได้ tree หน้าตาดังนี้



insert procedure ใน Oz เขียนดังนี้
proc {Insert Key Value TreeIn ?TreeOut}
if TreeIn == nil then TreeOut = tree(Key Value nil nil)
else
local tree(K1 V1 T1 T2) = TreeIn in
if Key == K1 then TreeOut = tree(Key Value T1 T2)
elseif Key < K1 then
local T in
TreeOut = tree(K1 V1 T T2)
{Insert Key Value T1 T}
end
else
local T in
TreeOut = tree(K1 V1 T1 T)
{Insert Key Value T2 T}
end
end
end
end
end

?TreeOut ที่บรรทัดบนสุดหมายความว่า
ตัวแปรนี้เป็น output parameter (แสดงว่า return parameter ได้หลายตัว)

tree(key value left right) คือ tuple data type
(คิดว่า implement ข้างใน คงจะเป็น linked-list)

local tree(K1 V1 T1 T2) = TreeIn
อันนี้คือการ declare variable ที่ชื่อ K1, V1, T1, T2
โดยการเปรียบเทียบ structure ของ LHS (left-hand-size) กับ RHS
ดังนั้นถ้า TreeIn มี value = (pok 1 nil nil)
ค่า K1 ก็จะเท่ากับ pok
V1 ก็จะเท่ากับ 1, ...

ทดลองเขียน scheme ที่ทำแบบนี้บ้าง
(เพราะ scheme ก็เป็น functional programming เหมือนกัน)
(define (make-tree key value left right)
(list 'TREE key value left right))

(define (get-key tree-in)
(cadr tree-in))

(define (get-value tree-in)
(caddr tree-in))

(define (get-left tree-in)
(cadddr tree-in))

(define (get-right tree-in)
(cadddr (cdr tree-in)))

(define (insert-tree key value tree-in)
(if (eq? tree-in '()) (make-tree key value '() '())
(let ((root-key (get-key tree-in))
(root-value (get-value tree-in))
(left-tree (get-left tree-in))
(right-tree (get-right tree-in)))
(cond ((string=? key root-key)
(make-tree key value left-tree right-tree))
((string<? key root-key)
(make-tree root-key root-value
(insert-tree key value left-tree)
right-tree))
(else
(make-tree root-key root-value
left-tree
(insert-tree key value right-tree)))))))

code ยาวกว่าหน่อย เพราะพยายามเขียนแบบสื่อความหมาย

สุดท้ายก็ลอง ruby บ้าง
โดย ruby จะมี method อยู่ 2 แบบ
แบบที่ 1 ชื่อ insert ใช้วิธีแก้ไข tree structure เลย
ส่วนแบบที่ 2 ชื่อ insert_immutable ซึ่งเรียนแบบวิธีการ
ที่ Oz กับ Scheme ใช้
class Node
attr_accessor :key, :value, :left, :right
def initialize (key, value, left, right)
@key = key
@value = value
@left = left
@right = right
end
end

def insert (key, value, node)
case
when node.key == key
node.value = value
when node.key > key
if node.left == nil
node.left = Node.new(key, value, nil, nil)
else
insert(key, value, node.left)
end
else
if (node.right == nil)
node.right = Node.new(key, value, nil, nil)
else
insert(key, value, node.right)
end
end
end

def insert_immutable(key, value, node)
case
when node == nil
Node.new(key, value, nil, nil)
when node.key == key
Node.new(key, value, node.left, node.right)
when node.key > key
Node.new(node.key,
node.value,
insert_immutable(key, value, node.left),
node.right)
else
Node.new(node.key,
node.value,
node.left,
insert_immutable(key, value, node.right))
end
end


ruby ไม่ได้เขียนแบบ object แท้
ลองแล้วมันไม่เหมาะกับ immutable style
code มันดูเยิ่นเย้อ

Related link from Roti

Futzmonkey

อ่านการ์ตูนนี่แล้วขำดี Futzmonkey

คำแปลประกอบ
Futz - To waste time or effort on frivolities;
frivolous - not serious in content or attitude or behavior;

ช่วงนี้ผมโดนเจ้า Futzmonkey attack บ่อย
เมื่อวานกำลังนั่ง เขียน spec ใน wiki อยู่
เกิดต้องทำตารางแล้วรู้สึกหงุดหงิดกับการพิมพ์
ก็เลยมองหา emacs mode ที่ช่วยพิมพ์ html ได้เร็วๆ
เสียเวลาไป 2 ชั่วโมง โดยไม่ได้ solution เลย
(ถ้าตั้งหน้าตั้งตาพิมพ์ต่อไป ก็ใช้เวลาไม่ถึง 5 นาทีหรอก)

Related link from Roti