- แก่นของ Lisp ไม่ได้อยู่ที่ไวยากรณ์วงเล็บ แต่คือวิธีคิดในการ ขยายภาษาให้เข้ากับปัญหา และคุณค่าที่แท้จริงจะปรากฏเมื่อเข้าใจทั้ง REPL, แพ็กเกจ, symbol, condition และ restart
- ด้วย homoiconicity ที่ทั้งโค้ดและข้อมูลถูกแทนด้วยลิสต์ แมโครจึงสามารถจัดการโค้ดก่อนประเมินผลได้เหมือนข้อมูล เพื่อสร้างโครงสร้างควบคุมและนามธรรมทางไวยากรณ์ใหม่ ๆ
- แม้ Common Lisp จะไม่มี
while แต่สามารถเพิ่มได้ด้วย defmacro อย่างไรก็ตาม หากเลียนแบบด้วยฟังก์ชัน อาร์กิวเมนต์จะถูกประเมินผลทันที ทำให้ body กลายเป็นค่า ไม่ใช่โค้ด
- การพัฒนา Lisp ใกล้เคียงกับ การพัฒนาแบบขับเคลื่อนด้วย REPL ที่ประเมินโค้ดเข้าไปในโปรเซสที่กำลังรันอยู่ต่อเนื่อง สามารถนิยามฟังก์ชัน แมโคร และตัวแปรใหม่ได้ โดยให้โปรแกรมวิวัฒน์ต่อไปโดยไม่ต้องหยุด
- เมื่อความสามารถในการขยายภาษารวมกับระบบแบบ live จะสามารถสร้าง ซอฟต์แวร์ที่ขยายได้ ซึ่งเปิดเผย DSL ภายในให้ผู้ใช้ใช้งานได้ โดยมี AutoLISP และ Emacs เป็นตัวอย่างเด่น
Lisp ต้องการเซนส์การเขียนโปรแกรมที่ต่างออกไป
- โปรแกรมเมอร์ที่พบ Lisp ครั้งแรกมักรู้สึกแปลกกับไวยากรณ์ที่มีวงเล็บจำนวนมาก การย่อหน้าที่เป็นเอกลักษณ์ และวิธีที่
format ใช้อาร์กิวเมนต์แรกเพื่อระบุ standard output
- การเรียนรู้ Lisp ไม่ใช่แค่อ่านโค้ด แต่ต้องจัดการแพ็กเกจและ symbol, การสร้างโปรเจกต์, การนำไลบรารีเข้ามาใช้, REPL, condition และ restart ด้วย
- การเปลี่ยนแปลงที่ใหญ่กว่านั้นปรากฏในวิธีประกอบอัลกอริทึม
- Lisp ทำให้สิ่งที่ทำได้ยากในภาษาอื่นเป็นไปได้ และทำให้รูปแบบของอัลกอริทึมเปลี่ยนไปด้วย
- แนวทางจะกลายเป็นการขยายภาษาขึ้นมาก่อนให้เหมาะกับปัญหา แล้วจึงเขียนโปรแกรมด้วยภาษานั้น
- Blub paradox เป็นแนวคิดที่อธิบายว่าทำไมโปรแกรมเมอร์ที่เคยใช้แต่ภาษาที่ทรงพลังน้อยกว่าจึงมองเห็นจุดแข็งของ Lisp ได้ยาก
ภาษาที่ขยายตัวเองได้
- Lisp สามารถขยายตัวเองได้ และผู้เชี่ยวชาญ Lisp เรียกสิ่งนี้ว่า programmable programming language
- เครื่องมือหลักคือ
macro
- ไม่ได้หยุดอยู่แค่การลดโค้ดซ้ำเหมือนแมโครของ C, Rust หรือ Swift
- แมโครของ Lisp สามารถสร้างองค์ประกอบใหม่ที่กลายเป็นส่วนหนึ่งของภาษาได้
- Common Lisp ไม่มีตัวดำเนินการ
while พื้นฐาน แต่สามารถเพิ่มเองได้ด้วย defmacro
(defmacro while (condition &body body)
`(loop while ,condition do
(progn ,@body)))
- แมโคร
while นี้จะรันคำสั่งหลายคำสั่งใน body ตราบเท่าที่ condition เป็นจริง
loop เป็นแมโครสำหรับเขียนการวนซ้ำที่ซับซ้อน
progn รัน expression หลายตัวตามลำดับและคืนผลลัพธ์ของ expression ตัวสุดท้าย
- ผลลัพธ์คือสามารถใช้รูปแบบ
(while ...) แทน (loop while ... do (progn ...)) ได้ ทำให้โค้ดสั้นลงและมีโครงสร้างคล้าย while ของ C
ความแตกต่างชี้ขาดระหว่างแมโครกับฟังก์ชัน
- หากสร้างพฤติกรรมเดียวกันด้วยฟังก์ชัน
fake-while จะล้มเหลว
(defun fake-while (condition body)
(loop while condition do
(funcall body)))
- ในการเรียก
fake-while อาร์กิวเมนต์จะถูกประเมินผลก่อน
condition กลายเป็นค่าจริง t
(print counter) ภายใน progn ถูกเรียกใช้ และ (decf counter) คืนค่า 2
body กลายเป็นค่า 2 ไม่ใช่บล็อกโค้ด
- หลังจากนั้น
funcall คาดหวังฟังก์ชัน แต่ได้รับ 2 จึงเกิด type error เช่น The value 2 is not of type FUNCTION
- ในทางกลับกัน แมโคร
while จะไม่ประเมิน condition และ body ทันที แต่เก็บรักษาไว้
- สามารถตรวจสอบผลลัพธ์การขยายได้ด้วย
macroexpand-1
- คอมไพเลอร์ได้รับโค้ดในรูปแบบที่ขยายแล้วคือ
(LOOP WHILE ... DO (PROGN ...))
- แมโครต่างจากฟังก์ชันตรงที่ไม่ประเมินอาร์กิวเมนต์ล่วงหน้า แต่จัดการเป็น ข้อมูลล้วน จึงทำการแปลงแบบนี้ได้
ลิสต์, s-expression และ homoiconicity
- โปรแกรม Lisp ประกอบด้วย symbolic expression หรือ s-expression ต่อเนื่องกัน
- s-expression แบ่งเป็นสองประเภท
- อะตอม (atom): หน่วยข้อมูล เช่น ตัวเลข สตริง หรือ symbol
- ลิสต์ (list): คอลเลกชันที่บรรจุอะตอมหรือลิสต์อื่น
- ชื่อ Lisp มาจาก LISt Processing และคำสั่งที่ประกอบเป็นโปรแกรมก็ถูกแทนด้วยลิสต์
- ใน Lisp ลิสต์เป็นทั้งโครงสร้างข้อมูลหลักและเป็นวิธีเขียนโค้ด
- คุณสมบัติที่ทั้งโค้ดและข้อมูลถูกแทนด้วยลิสต์เรียกว่า homoiconicity
- ลิสต์เดียวกันอย่าง
(+ 1 2) จะทำงานต่างกันตามว่าถูกประเมินผลหรือไม่
(+ 1 2) ถูกประเมินเป็นโค้ดและคืนค่า 3
'(+ 1 2) ไม่ถูกประเมิน และคืนกลับมาเป็นลิสต์ข้อมูลตามเดิม
- Lisp ใช้ Polish notation โดยวางชื่อฟังก์ชันไว้เป็นองค์ประกอบแรกของลิสต์ แล้วตามด้วยอาร์กิวเมนต์
- เพราะเส้นแบ่งระหว่างโค้ดกับข้อมูลบางมาก แมโครจึงสามารถแปลงซอร์สโค้ด และสร้าง โปรแกรมที่เขียนโปรแกรม ได้
นามธรรมของโค้ดที่แมโครสร้างขึ้น
- เมื่อขยายภาษา จะสามารถสร้างองค์ประกอบใหม่ที่มีพลังในการสื่อความหมายมากขึ้นสำหรับขอบเขตเฉพาะของโปรแกรม
- boilerplate ที่ซ้ำ ๆ สามารถแทนที่ด้วยแมโครที่ปรับแต่งเอง เพื่อลดโค้ดและประหยัดเวลา
- สามารถสร้างโครงสร้างควบคุมใหม่เพื่อควบคุมการเข้าถึงทรัพยากรและการประเมินผล form ได้
- แมโครสร้างโค้ด ปรับปรุงประสิทธิภาพ และมอบ นามธรรมทางไวยากรณ์ ที่ซ่อนโค้ดซับซ้อนและเกิดข้อผิดพลาดได้ง่าย
Lisp เป็นระบบแบบ live
- Lisp ถูก扱ในฐานะ ระบบ live ที่กำลังรันอยู่ มากกว่าจะเป็นเพียงภาษาโปรแกรมธรรมดา
- ในภาษาทั่วไป มักมี flow คือเขียนโค้ดในเอดิเตอร์ แล้วคอมไพล์และรันเพื่อสังเกต ทดสอบ และดีบัก
- ใน Lisp จะเริ่มจากสตาร์ตโปรเซส Lisp ก่อน เชื่อมเข้ากับ REPL แล้วโหลดโปรเจกต์เข้าไปในโปรเซสนั้น
- REPL ย่อมาจาก Read-Eval-Print Loop เป็นสภาพแวดล้อมแบบโต้ตอบที่ประเมินโค้ดและเห็นผลลัพธ์ได้ทันที
- ทำหน้าที่เหมือนหน้าต่างสำหรับมองเข้าไปในโปรเซส Lisp ที่กำลังรันโปรแกรมปัจจุบันอยู่
- นักพัฒนา Lisp ประเมินโค้ดต่อเนื่องภายในโปรเซสที่กำลังรัน และตรวจผลลัพธ์ได้ทันทีใน REPL
- ทดสอบฟังก์ชันรายตัว
- query ฐานข้อมูล
- ตรวจสอบตัวแปร
- งานอย่างการดีบักก็ทำได้ใน REPL
- โปรเซส Lisp ไม่จำเป็นต้องหยุด และอาจมีชีวิตอยู่ได้หลายสัปดาห์
- ฟังก์ชัน แมโคร และตัวแปรจะถูกนิยามและนิยามใหม่ต่อเนื่องในหน่วยความจำภายในที่เรียกว่า environment และ flow แบบนี้เรียกว่า การพัฒนาแบบขับเคลื่อนด้วย REPL
Hot reloading ใน Lisp
- ในเว็บฟรอนต์เอนด์ ประสบการณ์ที่โค้ด JavaScript ถูก hot reload ผ่านการบันทึกไฟล์หรือรีเฟรชหน้าเป็นเรื่องที่พบได้ทั่วไป
- hot reloading โดยทั่วไปพึ่งพาเครื่องมือและเทคนิคแยกต่างหาก เช่น การเฝ้าดูไฟล์ การคอมไพล์โมดูลที่เปลี่ยนใหม่ และการฉีดการเปลี่ยนแปลงผ่าน WebSocket
- ไม่ใช่ทุกซอฟต์แวร์สแต็กจะให้ hot reloading ในระดับเดียวกัน
- backend framework บางตัวต้องคอมไพล์ใหม่
- สภาพแวดล้อมพัฒนาเดสก์ท็อปและมือถือมีสภาพปะปนกันไป
- ภาษาระดับต่ำต้องคอมไพล์ทั้งหมดทุกครั้ง
- ใน Lisp, hot reloading ไม่ใช่เครื่องมือแยก แต่เกิดขึ้นอย่างเป็นธรรมชาติเมื่อประเมินโค้ดในสภาพแวดล้อมแบบ live
- เมื่อกำหนด symbol ใหม่ ฟังก์ชัน ข้อมูล และแมโครทั้งหมดจะใช้ definition ใหม่
- ความจำเป็นในการหยุดและคอมไพล์ แยกรันเทสต์ หรือใช้ดีบักเกอร์พิเศษลดลง
- การเขียนโปรแกรม Lisp ใกล้เคียงกับการ วิวัฒน์ โปรแกรม มากกว่าการประกอบโปรแกรมขึ้นมา
ซอฟต์แวร์ที่ขยายได้
- ความสามารถในการขยายภาษาและระบบแบบ live ทำให้ใน Lisp สร้าง ซอฟต์แวร์ที่ขยายได้ ได้ง่าย
- โปรแกรมเดสก์ท็อปทั่วไปขยายได้ผ่านปลั๊กอินหรือภาษาสคริปต์
- นักพัฒนาต้องออกแบบและดูแลระบบ extension
- ผู้ใช้ต้องเรียนรู้ API เฉพาะสำหรับเขียนปลั๊กอินหรือ extension
- ใน Lisp การใช้แมโครเพื่อ encapsulate พฤติกรรมและทำให้นำกลับมาใช้ซ้ำได้ง่าย จะนำไปสู่การเขียน DSL อย่างเป็นธรรมชาติ
- หากต้องการทำให้ซอฟต์แวร์ขยายได้ ก็เปิดให้ผู้ใช้ใช้งาน DSL ที่สร้างไว้ภายใน
- ในตัวอย่างเซิร์ฟเวอร์ CMS สามารถเปิดเผยแมโคร
html สำหรับสร้างหน้าเว็บฝั่งเซิร์ฟเวอร์ให้ผู้ใช้ได้
- ผู้ใช้สามารถใช้ตัวแปร Lisp, การวนซ้ำ
dolist และการฟอร์แมตสตริงด้วย format ร่วมกันได้โดยตรง
- ไม่จำเป็นต้องเรียนรู้ไวยากรณ์แยกต่างหากอย่าง
{{ user_name }} หรือ {% for %} เหมือนภาษาเทมเพลตแบบดั้งเดิม
- DSL นี้สืบทอดความสามารถของ Lisp มาเต็ม ๆ ทั้งเงื่อนไข recursion, higher-order function และการดีบักทีละขั้นใน REPL
- ในตัวอย่างซอฟต์แวร์กราฟคณิตศาสตร์ สามารถเปิดเผย DSL สำหรับสมการและการวาด เพื่อให้ผู้ใช้วาดเส้นโค้งและจุดด้วยโค้ดเพียงเล็กน้อย
ตัวอย่างจริงและตำแหน่งของ Lisp
- AutoCAD ใช้ AutoLISP สำหรับทำงานซ้ำอัตโนมัติและสร้างเรขาคณิตที่ซับซ้อน
- Emacs เป็น text editor ที่ส่วนใหญ่ถูก implement ด้วย Lisp dialect ของตัวเอง จึงมีความสามารถในการขยายสูง
- ตัวอ่าน PDF
- เว็บเบราว์เซอร์
- ไคลเอนต์อีเมล
- RSS reader
- terminal multiplexer
- Git client
- เครื่องเล่นเพลง
- chat client
- สเปรดชีต
- IRC client
- มีการยกตัวอย่างไปจนถึง desktop window manager
- R. M. Stallman ประเมินว่า Lisp เป็นภาษาที่ทำให้เข้าใจความหมายของภาษาโปรแกรมที่ทรงพลังและงดงาม
- ความคาดหวังว่า Lisp จะถูกใช้แพร่หลายเหมือนภาษาหลักในสักวันหนึ่งไม่ได้เกิดขึ้นจริง และดูเหมือนว่าในอนาคตก็มีโอกาสน้อย
- ถึงอย่างนั้น Lisp ก็อยู่รอดมาตั้งแต่ทศวรรษ 1960 และกลายเป็นภาษาโปรแกรมที่ยังใช้งานอยู่ที่เก่าแก่เป็นอันดับถัดจาก Fortran
- คุณค่าของ Lisp ไม่ได้มาจากฟีเจอร์เดี่ยว ๆ อย่างความสามารถในการขยาย สภาพแวดล้อมแบบโต้ตอบ หรือ REPL แต่มาจาก การผสานกัน ของสิ่งเหล่านั้น
1 ความคิดเห็น
ความเห็นจาก Hacker News
การเขียนโปรแกรมตั้งอยู่บนความตึงเครียดระหว่าง ด้านสว่าง กับ ด้านมืด
ด้านสว่างคือแนวทางที่ป้องกันไม่ให้โปรแกรมเมอร์ทำพลาด: เอา
gotoออก ใส่ static type และทำให้ไม่สามารถเขียนสิ่งที่ก่อบั๊กได้ด้านมืดคือแนวทางที่มอบพลังให้โปรแกรมเมอร์: เปิดทางให้ใช้ macro, operator overloading, self-modifying code ไปจนถึง regex หลายบรรทัดได้อย่างเต็มที่
Lisp ชัดเจนว่าอยู่ฝั่งด้านมืดในแง่ที่โปรแกรมเมอร์ทำอะไรก็ได้ แต่ก็น่าสนใจที่มันยังได้รับความเคารพจากโปรแกรมเมอร์สายด้านสว่างด้วย อาจเป็นเพราะความเรียบง่ายของภาษาทำให้มันดูเป็นแบบเพลโตและแทบจะเสื่อมทรามไม่ได้ หรืออาจเป็นเพราะ Lisp บริสุทธิ์เสียจนเหมือนเทพเจ้าที่ให้กำเนิดจักรวาลแห่งการเขียนโปรแกรมและโอบรับทั้งสองด้านไว้พร้อมกัน
เราเลือกไม่ได้ว่าจะได้ร่วมงานกับใคร และก็เลือกไม่ได้ด้วยว่าทักษะของคนในทีมจะเป็นอย่างไร เมื่อเพื่อนร่วมงานที่มีประสบการณ์น้อยกว่าทำพลาด ยิ่งภาษาเปิดกว้างมาก ผลกระทบก็ยิ่งใหญ่
จึงต้องมี code review แต่แบบนั้นก็เท่ากับเปลี่ยนโปรแกรมเมอร์ที่ชำนาญให้กลายเป็นครู เวลาที่ใช้ไปกับการยกระดับฝีมือของโปรแกรมเมอร์คนอื่นส่วนหนึ่งจึงสูญเปล่า เพราะคนในสายอาชีพนี้เข้าออกงานกันได้ตลอด AI อาจเปลี่ยนสมการนี้ได้
สุดท้ายแล้วแก่นสำคัญคือการรักษาทีมขนาดเล็กที่มีฝีมือสูงไว้ให้ได้ แต่การเมืองในบริษัททำให้เรื่องนี้ไม่ง่าย เช่น มักมีการเพิ่มนักพัฒนาเข้ามาเพราะคำนึงถึง bus factor หรือเพื่อย่นระยะเวลาออกของ
ระบบที่ต้องการความน่าเชื่อถือสูงก็เขียนด้วย Erlang ได้เช่นกัน ซึ่งถ้ามองแบบหยีตาหน่อยก็อาจนับเป็น dialect ของ Lisp อีกแบบหนึ่งได้ ยังมี LFE ซึ่งเป็น Erlang สไตล์ Lisp ที่ใช้ S-expression ด้วย
แก่นของความน่าเชื่อถือใน Erlang ไม่ได้อยู่ที่การป้องกันข้อผิดพลาดแบบสุดโต่ง แต่อยู่ที่ การกู้คืนจากข้อผิดพลาด ส่วนการแบ่งแบบสว่าง/มืดนั้นก็เป็นไอเดียที่ชอบ
ถึงจะไม่มี static type และ macro อาจกลายเป็นความวุ่นวายได้ แต่เส้นฐานของการคิดแบบ declarative/functional นั้นแข็งแรงกว่ามาก จึงให้จุดเริ่มต้นที่ดีกว่าสำหรับการคิดและให้เหตุผลกับโปรแกรมอย่างชัดเจน
การแบ่งเป็นสว่าง/มืดดูเรียบง่ายเกินไปหน่อย สมดุลของภาษาโปรแกรม เป็นหัวข้อที่ซับซ้อนและน่าสนใจมาก
หลังจากลองใช้หลายภาษาอยู่หลายปี สุดท้ายก็พบว่ามันเป็นเรื่องของบริบทการใช้งาน รสนิยมส่วนตัว และเป้าหมาย ไม่มีอะไรอย่าง “ภาษาโปรแกรมที่ดีที่สุดตลอดกาล” และก็ไม่มี “ดีที่สุดสำหรับการเขียนโปรแกรมฝั่งด้านสว่าง” หรือ “ดีที่สุดสำหรับการเขียนโปรแกรมฝั่งด้านมืด” เช่นกัน
ในศิลปะการวาดภาพก็ไม่มีด้านสว่าง/ด้านมืดแบบนั้น แน่นอนว่ามีภาพที่ยิ่งใหญ่กว่าภาพอื่น แต่ไม่มี “ภาพที่ดีที่สุด” ที่ทุกคนจะรู้สึกว่าสวยที่สุดเมื่อเทียบกับภาพอื่นทั้งหมด
https://en.wikipedia.org/wiki/Malbolge
https://en.wikipedia.org/wiki/Clean_(programming_language)
https://en.wikipedia.org/wiki/K_(programming_language)
ช่วงไม่กี่เดือนที่ผ่านมา มี editor และเครื่องมือใหม่ยอดเยี่ยมออกมาหลายตัว ไม่ควรพลาด
Mine เป็นแอปดาวน์โหลดเดี่ยวที่ให้ทุกอย่างที่จำเป็นสำหรับการสัมผัส workflow การพัฒนาแบบ interactive และ incremental รวมถึง hot reloading และการดีบักแบบทันที รองรับ CL และ Coalton
https://coalton-lang.github.io/20260424-mine/
OLIVE เป็นปลั๊กอินทำมือสำหรับ VSCode ส่วน ICL คือ REPL ใหม่สำหรับเทอร์มินัลและเบราว์เซอร์ที่มีความสามารถขั้นสูง นอกจากนี้ยังมี JupyterLite kernel ที่อิงกับ JSCL เป็นของแถม จึงรันได้บนเบราว์เซอร์ 100%
ดูทั้งหมดได้ที่นี่: https://lispcookbook.github.io/cl-cookbook/editor-support.ht...
mineไม่เจอ มีลิงก์ไหม?ดูเหมือนเว็บไซต์จะมี บั๊กเรื่อง syntax highlighting โค้ดที่แทรกอยู่ในเนื้อหาหลักแสดงเป็นสีดำ และถ้าใช้เมาส์ลากเลือกจึงจะเห็นข้อความจริง
เจอบั๊กเดียวกันทั้งบน Chrome เดสก์ท็อปและ Safari บน iPad
วิธีแก้ขัดคือเปิด debugger ของเบราว์เซอร์ที่องค์ประกอบโค้ดสักตัว แล้วเพิ่ม
color: whiteเข้าไปในสไตล์:not(pre) > codeมีบทความมากมายที่สรรเสริญข้อดีของ Lisp แต่อยากเห็นบทความที่ วิจารณ์อย่างสุขุม ต่อ Lisp แนวคิดของมัน และตำแหน่งของมันในระบบนิเวศของภาษาโปรแกรมมิงด้วย
บทความแบบนี้หรือบทความของ PG ที่อ้างถึงตรงนี้ สุดท้ายก็ใกล้เคียงกับแนว “คนที่รู้ก็รู้กัน” อยู่ดี
เข้าใจเสน่ห์ของมัน และเข้าใจข้ออ้างที่บทความนี้เสนอทั้งโดยตรงและโดยนัย
การเขียนโปรแกรมคอมพิวเตอร์สุกงอมขึ้นมากตลอด 60 ปีที่ผ่านมา อยากเห็นบทความที่มีการพิจารณาไตร่ตรองมากกว่านี้
ภาษาอื่นก็มีปัญหานี้ แต่คิดว่า Lisp เป็นหนักกว่า
ข้อเสียอย่างที่สองคือมันกินเวลาของคนที่มีความสามารถพอเป็นปี ๆ แต่ผลลัพธ์กลับไม่คุ้มกับเวลาที่ลงทุนไป Python แบบนั้นก็เพียงพอแล้ว คิดว่าน่าจะเอาเวลาส่วนใหญ่ที่ใช้กับ Lisp ไปทำอย่างอื่นมากกว่า
Clojure, Clojurescript, Clojure-Dart, Fennel, Jade, Jank, Jolt, Coalton เป็นภาษาที่ค่อนข้างใหม่และยังพัฒนาอยู่จนถึงตอนนี้ เท่าที่นึกออกตอนนี้ก็มีประมาณนี้ และยังมีอีกมาก
ในความหมายหนึ่ง Lisp ไม่ใช่ภาษาโปรแกรมมิง แต่เป็น แนวคิด มันมีอิทธิพลต่อภาษาโปรแกรมมิงแทบทั้งหมดที่เราใช้กันทุกวันนี้ และยังคงมีอิทธิพลอยู่ การจะวิจารณ์แนวคิดอย่าง “สุขุม” นั้นทำได้ยาก และคล้ายกับการวิจารณ์ทฤษฎีกลุ่ม อย่างไรก็ตาม เราสามารถถกข้อดีข้อเสียของการนำแนวคิดนั้นไปทำเป็นรูปธรรมแบบใดแบบหนึ่งได้
async/awaitหรือโมเดล concurrency ที่เป็นมาตรฐาน และมาตรฐานก็ไม่ได้อัปเดตมาตั้งแต่ปี 1995 ดังนั้นก็คงจะไม่เกิดขึ้นในอนาคตสำหรับบางคนมันดึงดูดทางความคิดมาก อยากเปรียบมันกับแนวดนตรีเฉพาะกลุ่มมาก ๆ คนที่ชอบมีไม่มาก แต่คนเหล่านั้นชอบมันอย่างเข้มข้นมาก มันเหมือน Stockhausen แห่งวงการโปรแกรมมิง
โดยพื้นฐานแล้วมันคือแฟนด้อม เป็นแฟนด้อมที่อยู่ยืนยาวอย่างน่าทึ่ง แต่ไม่เคยทะลุไปสู่กระแสหลัก และก็คงมีโอกาสน้อยที่จะเป็นแบบนั้นต่อไป ตอนนี้ตำแหน่งของมันยิ่งแย่ลงอีก ถ้ามี LLM ติดอาวุธอยู่แล้วและแทบไม่สนใจตัวโค้ดเลย จะสั่งให้เขียนด้วย Lisp ไปทำไม?
พอทำ Lisp มานานเกินไป ก็จะเลิกเห็นคุณค่าของความสามารถเหล่านั้นอย่างเหมาะสม แต่พอไปเห็นผู้คนทำลายตัวเองในภาษาที่เป็นกระแสหลักกว่าและเสี่ยงทางเศรษฐกิจน้อยกว่า ด้วยความช็อกและสยองขวัญ ก็จะกลับมารู้สึกถึง คุณค่าของ Lisp อีกครั้งทันที
ในงานเชิงพาณิชย์ ภาษาเฉพาะโดเมน เป็นแอนติแพตเทิร์น มีใครสักคนสร้างภาษาเฉพาะโดเมนที่เอกสารน้อยและมีแต่ตัวเองที่เข้าใจ แล้วก็จากไป
โปรแกรมเมอร์ที่ตามมาต้องพยายามถอดรหัสภาษาแปลก ๆ นี้ แทบทุกครั้งการใช้โครงสร้างและความสามารถของภาษามาตรฐานจะดีกว่า โค้ดนั้นถูกอ่านบ่อยกว่าถูกเขียน
สิ่งที่คัดค้านจริง ๆ อาจเป็นการขาด referential transparency มากกว่า ซึ่งถ้าจะให้ยุติธรรมก็เป็นปัญหาในหลายภาษา รวมถึง Lisp ด้วย
ตัวอย่างที่ดีคือแมโคร
LOOPของ Common Lisp เอง ถ้าการใช้งานของใครบางคนเข้าใจยาก ก็ให้ Lisp ขยายมันเป็นคำเรียกพื้นฐานแบบไม่ใช้LOOPที่ยืดยาวกว่าได้ และไม่จำเป็นต้องเข้าใจLOOPเลยอันที่จริงยังแทนที่ฟอร์ม
LOOPด้วยโค้ดที่ขยายแล้วได้ด้วยนี่เป็นความแตกต่างสำคัญจากภาษาอื่นส่วนใหญ่ ซึ่งโค้ดภาษาเฉพาะโดเมนมักเป็นโครงสร้างข้อมูลที่ถูกตีความในภายหลัง
Lisp หลายตระกูลมีจุดเด่นที่ทรงพลังและไม่เหมือนใครจริง ๆ แต่ก็อยากให้บทความแนวนี้เลิกพูดถึง REPL กับ hot reloading ซ้ำ ๆ เสียที
REPL เป็นเรื่องพื้นฐานมานานแล้วในภาษาตีความต่าง ๆ แม้กระทั่งบางภาษาคอมไพล์ ส่วน hot reloading ก็ไม่ได้มีเอกลักษณ์เฉพาะ และก็ไม่ได้ถูกใช้อย่างแพร่หลายเป็นพิเศษ การต้องจัดการทั้งสถานะและแพตช์ทำให้มีเหตุผลว่าทำไมแนวปฏิบัติที่ดีจึงมักถือว่าการรีเซ็ตทั้งหมดเพื่อให้อนุมานได้ง่ายขึ้นเป็นทางเลือกที่เหมาะกว่า
เพราะแบบนั้นการพัฒนาเชิงโต้ตอบจึงทำได้มากกว่าภาษาตีความอื่น ๆ มาก
แน่นอนว่ามันไม่ได้สมบูรณ์แบบ แต่สำหรับการเปลี่ยนแปลงประเภทที่ทำตอนวนปรับปรุงประสบการณ์ผู้ใช้ มันทำงานได้ดีมาก
แต่อยากเน้นว่าหลายส่วนที่เป็นด้านลึกของ hot reloading นั้นถูกจัดการไว้แล้วใน Common Lisp เช่นเดียวกับที่ REPL มักไม่ได้ใช้เป็นที่พิมพ์คำสั่งตรง ๆ แต่เป็นอินเทอร์เฟซที่ทรงพลังมากสำหรับให้ image ที่กำลังรันอยู่กับเครื่องมือทำงานร่วมกัน
ถึงอย่างนั้นก็เห็นด้วยว่า แค่การมีสิ่งเหล่านี้อยู่ ทุกวันนี้ไม่ได้ถือว่าพิเศษมากนัก
ถ้านิยามคลาสถูกแทนที่ด้วยการรีโหลด แต่ยังมีอินสแตนซ์เก่าค้างอยู่ จะทำอย่างไร? Lisp ตระกูล Common Lisp มีคำตอบที่ใช้การได้กับคำถามแบบนี้ แต่ Lisp ที่คุณเจอทุกตัวไม่ได้มีแบบนั้นเสมอไป
Bash ก็รองรับ hot reloading เช่นกัน เคยพัฒนาโมดูลที่อัปเดตอยู่กับที่ด้วยการ
sourceแบบนี้$ . /path/to/script.shประโยชน์ใช้สอยของมันอาจมีจำกัด แต่ถ้าเริ่มต้นจากมุมมองว่าจะได้ใช้มันบ่อย ๆ ข้อจำกัดนั้นก็จะเริ่มหายไปค่อนข้างเร็ว
โดยส่วนตัวผมข้ามพ้นขั้นเหล่านี้มาแล้ว เคยใช้ Common Lisp, Forth และ Haskell และอ่าน 『On Lisp』 กับ 『Let Over Lambda』 อย่างเพลิดเพลิน
ตอนนี้ผมคิดว่าภาษาการเขียนโปรแกรมที่ดีที่สุดคือ Triage Calculus ของ Barry Jay ซึ่งใกล้เคียงกับ combinatory logic หรือ untyped lambda calculus
แต่ต่างจาก lambda calculus ตรงที่ Triage Calculus มีการอ้างอิงและการตรวจสอบภายในแบบที่คล้ายกับ
CARและCDRของ Lisp ทำให้เพิ่มการตรวจสอบชนิดข้อมูลได้ง่าย ดังนั้นใน TC ถ้าสร้าง abstraction ที่ถูกต้องได้ ก็จะมีไวยากรณ์แบบไหนก็ได้ตามที่ต้องการ มันคือภาษาการเขียนโปรแกรมสูงสุดอย่างแท้จริงTC แสดงให้เห็นว่าการแบ่งแยกระหว่างฟีเจอร์และไวยากรณ์ของภาษาในด้านหนึ่ง กับนิยามฟังก์ชัน/API ของ standard library หรือโค้ดผู้ใช้อีกด้านหนึ่ง เป็นการแบ่งขั้วแบบเทียม ทุกครั้งที่คุณเขียนโค้ดที่ตั้งใจให้ใช้ซ้ำได้ คุณก็กำลังเพิ่มบางอย่างเข้าไปในภาษา ทั้งหมดนี้สามารถแสดงได้เป็นพจน์บางตัวของ TC
การถกเถียงเรื่องไวยากรณ์ทั้งหมดเป็นเรื่องของความคุ้นชิน เพียงแต่ฟีเจอร์ไวยากรณ์อย่างหนึ่งที่ผมอยากได้จริง ๆ ใน TC คือ abstraction แบบ
let over lambdaเพราะการจัดเรียง combinator ด้วยมือนั้นค่อนข้างน่ารำคาญเขียนได้ดีมาก
เมื่อก่อนผมเคยคิดว่าสักวันหนึ่งทุกคนจะใช้ Lisp และเมื่อมีเครื่องมือกับไลบรารีที่ยอดเยี่ยมพร้อม ทุกอย่างก็คงจะยอดเยี่ยมไปหมด อันที่จริงแผนหลังเกษียณของผมก็คือการสร้างไลบรารีคุณภาพสูงสำหรับภาษา Lisp เพื่อช่วยเร่งกระบวนการนี้
การมาของ AI กำลังทำให้ความฝันนี้จบลงหรือเปล่า? สุดท้ายเราก็แค่แก้ปัญหาด้วยการยัดของปะปนเข้าไปมากขึ้นอีกครั้งใช่ไหม? แทนที่ปัญญาประดิษฐ์เหนือมนุษย์จะเขียนโค้ดด้วยภาษาการเขียนโปรแกรมที่ดีที่สุดเท่าที่เป็นไปได้ มันจะกลายเป็นว่าแค่โปรยโค้ด Python จำนวนมหาศาลแล้วดันต่อไปจนกว่าจะใช้ได้หรือไม่?
ผมไม่รู้ว่านี่สำคัญไหม ผมแค่อยากได้โลกที่มีความสง่างาม
“Jean-Marie Hullot ขณะทำงานอยู่ที่ INRIA ได้สร้าง ‘SOS Interface’ สำหรับ Macintosh ด้วย Lisp และนี่คือ ‘interface builder’ สมัยใหม่ตัวแรก”
https://denninginstitute.com/itcore/userinterface/GUIHistory...
อดคิดไม่ได้ว่าถ้าสิ่งนี้กลายเป็นผลิตภัณฑ์กระแสหลักของ Mac แทนที่จะย้ายไป NeXT และถูกใช้ร่วมกับ Objective-C มันจะเป็นอย่างไร
LISP เข้ากับผมได้ดีมาก ในวิชาเปรียบเทียบภาษาในมหาวิทยาลัย มีเพียงผมคนเดียวที่ทำการบ้าน LISP ได้ครบทั้งหมด และการเรียน LISP ก็ช่วยอย่างมากในการใช้ TeX ด้วย
สิ่งที่ผมอยากได้คือ GUI toolkit แบบ native หรือ cross-platform ที่เป็นโอเพนซอร์สและใช้ได้ดี พร้อมทั้งวิธีแจกจ่ายโปรเจกต์เป็นโค้ดคอมไพล์แบบสแตนด์อโลนได้อย่างง่ายดาย
มนุษย์สามารถใช้ทั้งสองอย่างเพื่อแสดงความคิดที่ดีได้ คิดกับภาษาว่าเป็นเครื่องมือจะดีกว่า สว่านกระแทกไม่ได้เหนือกว่าสว่านหมุนธรรมดาเสมอไป ถ้าจะสร้างเด็ค สว่านกระแทกอาจเหมาะกว่า แต่ทั้งคู่ก็ทำงานให้เสร็จได้
ผมนึกว่าบทความนี้จะเป็น https://web.archive.org/web/20120106121645/http://wiki.alu.o...
ทำให้นึกถึงตอนที่เคยตาม comp.lang.lisp อยู่ มันเหมือนละครอย่างหนึ่ง มีทั้งมนตร์แห่งการเขียนโปรแกรมและทั้งตัวละครกับเหตุการณ์ที่มีสีสันมากมาย