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