Monthly Archives: December 2016

Code as Data มีประโยชน์อย่างไร

มีคนเล่ามาทาง FB Message ว่า กำลังศึกษา Clojure อยู่ แต่ไม่ค่อยเข้าใจประโยชน์ของแนวคิด code as data

ผมเองก็ยังรู้สึกไม่ค่อยเข้าใจเหมือนกัน แต่ขอแชร์สิ่งที่ผมพอมองเห็น พอเข้าใจนะครับ

1. มันทำให้มี syntax เฉพาะของภาษาน้อย เพราะจำกัดอยู่แค่ data structure ของภาษา โดยทุกๆ อย่างมันอยู่ใน รูปนี้หมด


(form arg1 arg2 arg3 ... argN)

เช่น def, defn, if, let ก็อยู่ในรูปนี้ทั้งหมด มัน consistent ดี

2. ไม่มี syntax ไม่เคยต้องเรียน syntax ใหม่ มีแต่ไลบราลีใหม่ อะไรที่เติมเข้ามาในภาษาแค่เราเข้าใจว่า ตัวแรกในวงเล็บ(form) มันทำอะไรก็จะทำให้เข้าใจมันทันที

3. พอ code เป็น data แล้วก็แปลว่าสามารถใช้ tool ที่ manage data มา manage code ได้ เช่น เวลาเขียน macro

4. Parser ของภาษาก็เขียนง่าย แล้วเวลาเขียนพวก tool เช่น refactoring tool ให้ ide, editor ก็ใช้ไลบราลีที่ manage code นี่แหละในการเขียน tool พวกนั้น

5. ส่งโค้ดผ่าน network ง่าย serialize ง่าย อาจจะไม่ใช่สิ่งที่ทำบ่อยๆ แต่เราสามารถเขียนระบบแบบส่ง code ไปรันบน server อื่นได้ เช่น network repl

6. นอกจาก code as data แล้ว เค้ายังนิยมออกแบบอย่างอื่นให้เป็น as data อีก เช่น config, html ทุกอย่างก็จะ consistent กันหมด ใช้ tool เดิมแนวคิดเดิมจัดการทุกอย่าง

เขียนครั้งแรกที่ https://www.facebook.com/groups/clojurethai/permalink/1235319406506550/

เชื่อมต่อ Clojure REPL เข้าไปที่ VM ที่ทำงานอยู่

คนที่เขียน Java มาอาจจะเคยต้อง restart server เป็น debug mode เพื่อต่อ debugger ของ IDE เข้าไป debug ปัญหา โดยมีความยุ่งยากคือต้อง restart ซึ่งอาจจะรบกวนการใช้งานของ user หรือบางครั้งหลังจาก restart แล้วปัญหาก็ดันหายไป

คนที่เขียน Ruby มาอาจจะเคย start irb บน server เพื่อลองรันคำสั่งต่างๆ แต่มันก็เป็นคนละโปรเซสกับที่ server ทำงานอยู่

บน Clojure เราสามารถเปิด port เอาไว้เชื่อมต่อ repl เข้าไปที่ VM หรือ server ที่ทำงานอยู่ได้ง่ายๆ โดยใช้ฟีเจอร์ที่ชื่อว่า Socket Server ซึ่งถูกเพิ่มเข้ามาใน Clojure เวอร์ชั่น 1.8

การใช้งานทำได้โดยการเพิ่ม option นี้เข้าไปเวลา start JVM

-Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}"

* :accept คือ ฟังก์ชันที่จะถูกเรียกเมื่อมีการติดต่อเข้ามาทาง socket

ในที่นี้ผมขอยกตัวอย่างรัน repl ปกติขึ้นมาหนึ่ง vm พร้อมเปิด socket ให้เชื่อมต่อ repl เข้ามาเพิ่มได้อีกละกัน

ปกติผมจะ start repl ด้วยคำสั่งนี้

$ rlwrap java -jar /path/to/clojure.jar

เราก็ทำการเพิ่ม option ข้างต้นเข้าไป

$ rlwrap java -Dclojure.server.repl="{:port 5555 :accept clojure.core.server/repl}" -jar /path/to/clojure.jar

เมื่อทำการรันคำสั่งด้านบนนี้ repl จะถูก start ขึ้นมาปกติ เมื่อ start เสร็จแล้ว เราสามารถ connect เข้าไปที่ VM นั้นผ่าน socket ได้โดยใช้ telnet ดังนี้

$ telnet localhost 5555

เราก็จะได้ repl ขึ้นมาอีกอันซึ่ง share data และ memory เดียวกับ repl แรกทั้งหมด เราสามารถทำทุกอย่างได้ตามชอบใจกับ VM นั้น

รายละเอียดเพิ่มเติมที่ Launching a Socket Server

เขียนครั้งแรกที่ https://www.facebook.com/groups/clojurethai/permalink/1231413573563800/