Friday, November 18, 2005

Re Party with Lisp

ช่วงนี้กำลังหัดเขียน common lisp อยู่
อ่าน post เรื่อง party ของ mk แล้ว
ก็เลยทดลองเขียน clisp ดูเล่นๆดีกว่า

เริ่มกันที่ funcation should-criticize?
ซึ่งเราจะใช้สั่ง run แบบนี้(should-criticize "ธีรยุทธ" "ทักษิณ")

(defun should-criticize? (a b)
(if (better? a b) t nil))

ความหมายก็คือ a มีคุณสมบัติพอที่จะวิจารณ์ b ได้หรือไม่
ก็ให้ call ไป function better? ถ้า return true
ก็จะ return t กลับไป ถ้าไม่ใช่ ก็จะ return nil (false ในความหมายของ lisp)

ลองนิยาม function better? ต่อ

(defun better (a b)
(if (> (how-good a) (how-good b)) t nil))

เขียนง่ายๆ ว่าถ้า a มีแต้ม how-good มากกว่า b
(how-good คือ function ที่ return คะแนนความดีกลับออกมา)
ก็ให้ return t (true)

ลองนิยาม function how-good
อืมม์อันนี้สิเริ่มยากแล้ว
เรารู้กันว่าความดีเป็น subjective แล้ว
a อาจจะดีกว่า b ในสายตา y
หรือ
b ดีกว่า a ในสายตา x
อย่างนี้ต้องย้อนกลับไป refactor code เดิม
ให้ส่ง c (คนที่มอง) มาด้วยดีกว่า
(งั้งเวลาสั่ง run ก็จะเป็นแบบนี้แทน (should-criticize "ธีรยุทธ" "ทักษิณ" "mk")))

(defun should-criticize? (a b c)
(if (better? a b c) t nil))

(defun better (a b c)
(if (> (how-good a c) (how-good b c)) t nil))


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

(setf *attrs* '("father" "business" "charisma" "pricky"))

(เอ้ คุณธีรยุทธ แกแต่งงานหรือยังหว่า?)

คราวนี้ต้อง loop ไปตาม list เพื่อเก็บคะแนนรวม
อืมม์ชักยากแล้วสิ ยังอ่านไม่ถึงบทที่ว่าเรื่อง iterator เลย

(defun how-good (subject object)
(let ((total 0))
(dolist (attr *attrs*)
(setf total (+ total (get-score subject object attr))))
total))

คนที่ไม่เคยใช้ lisp อาจจะร้องอุทานว่า "โอ อะไรกันนี้"
ส่วนผมที่พึ่งหัดใช้ ก็ยังร้องแบบเดียวกันอยู่
คำอธิบายก็คือ let เป็นการกำหนด scope ของตัวแปร
ในที่เราเขียนนี้ตัวแปร total จะมี life-cycle อยู่ใน ขอบเขตของ let เท่านั้น
ส่วน dolist เป็นการ loop ไปตาม list *attrs* ที่ให้มาโดย
ดึงค่าออกมาใส่ตัวแปร attr ทีละตัว
(setf x 1) มีความหมาย = int x = 1 ใน java
ส่วน get-score ก็คือ function ที่ return คะแนนที่ subject ให้กับ
object ในส่วนของคุณสมบัติต่างๆ
บรรทัดสุดท้ายก็คือการ return ค่า total กลับออกมา

อืมม์ดูแล้ว ลืมเรื่อง weight ไปเลย
เพราะแต่ละคนอาจจะให้นำ้หนักของ attributes ต่างๆไม่เท่ากันอีก
เปลี่ยนเป็นอย่างนี้ดีกว่า

(defun how-good (subject object)
(let ((total 0))
(dolist (attr *attrs*)
(setf total (+ total
(* (get-weight subject object attr)
(get-score subject object attr)))))
total))


เฮ้อ พอพอแค่ดีกว่า ไม่รู้จะ implement get-weight กับ get-score อย่างไงดี

Note:

CL-USER > (is-annoy-me "สนธิ")
T

แปลว่า ผมก็รำคาญสนธิเหมือนกัน
แต่ระหว่างทักษิณกับสนธิ, ผมรำคาญใครมากกว่ากันนั้น ไม่บอก

Related link from Roti

3 comments:

mk said...

เยี่ยมยอด!

งาน blognone ถ้าจัดได้จริง จะเชิญไปเป็นวิทยากร :) (ผมอยากฟัง Ruby on Rail นะ)

bact' said...

ผมไม่เคยสูบบุหรี่ ไม่อยากลอง ไม่จำเป็นต้องลอง

ผมรู้ว่าบุหรี่ไม่ดีนะ

งานเขียนหรือทฤษฎีมากมาย ที่มีอิทธิพลต่อชีวิตเราทุกวันนี้ ก็ไม่ได้มีทุกชิ้นที่เกิดจากการลงมือทำจริง แล้วค่อยสร้างค่อยเขียนออกมา
(อย่างมาร์กซก็ไม่ได้เป็นผู้ปฏิวัติ ส่วนเหมาก็ไม่ได้เป็นผู้วาดแผนการ ถ้าจะให้เครดิต ก็ต้องให้ทั้งคู่)

ผมว่าใครจะทำ จะคิด จะอะไรก็ได้
ขอให้แจ้งเจตนาให้ชัดเจน คนที่อ่านที่ฟัง จะได้ตีความง่าย ๆ

เสือมันร้าย แต่ก็ไม่อันตราย เพราะเรารู้ว่ามันร้าย

คนนี่เราไม่รู้ว่าร้ายหรือไม่ร้าย ก็เลยอันตราย

bact' said...

คนไม่ชอบสนธิก็เยอะ
แต่เชียร์สนธินะ

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


ผมรำคาญทั้งคู่แหละ
(ส่วนคนไหนมากกว่ากัน ก็ไม่บอก ... เลียนแบบ 555 :P)