2 คะแนน โดย GN⁺ 2024-05-13 | 1 ความคิดเห็น | แชร์ทาง WhatsApp

การนำ "Lisp in Lisp" ของ McCarthy มาเขียนด้วย Python

  • Lisp ที่ John McCarthy พัฒนาขึ้นในช่วงต้นทศวรรษ 1960 มีคุณสมบัติแบบ homoiconicity ทำให้โค้ดและข้อมูลสามารถสลับแทนกันได้

    • ใน Lisp เส้นแบ่งระหว่างโค้ดกับข้อมูลจึงไม่ชัดเจน
    • ด้วยเหตุนี้ Lisp จึงสามารถอธิบายตัวเองได้อย่างเป็นธรรมชาติ
  • โค้ดเพียงครึ่งหน้าที่ด้านล่างของหน้าที่ 13 ในคู่มือ Lisp 1.5 ก็คือตัว Lisp เอง

    • Alan Kay เรียกสิ่งนี้ว่า "สมการแมกซ์เวลล์ของซอฟต์แวร์"
    • โลกทั้งใบของการเขียนโปรแกรมถูกบีบอัดอยู่ในโค้ดเพียงไม่กี่บรรทัด
  • วิธีที่ดีในการทำความเข้าใจเรื่องนี้คือการนำโค้ด "Lisp in Lisp" มาเขียนใหม่ด้วย Python

    • โปรแกรมเมอร์ส่วนใหญ่ไม่คุ้นกับไวยากรณ์ของ Lisp แต่คุ้นกับไวยากรณ์ของ Python มากกว่า
    • เป้าหมายคือเขียนใหม่ด้วย Python โดยคงจิตวิญญาณของโค้ด Lisp ไว้ให้มากที่สุด

M-expression และ S-expression ของ Lisp

  • เดิมที Lisp มีไวยากรณ์อยู่สองแบบ

    • M-expression (meta expression): รูปแบบสำหรับโค้ด
    • S-expression (symbolic expression): รูปแบบสำหรับข้อมูล
    • ทั้งสองแบบมีความหมายเหมือนกัน
  • โค้ด "Lisp in Lisp" ถูกเขียนด้วย M-expression และใช้เพื่ออิมพลีเมนต์ S-expression Lisp

  • วิธีหนึ่งคือแปลง M-expression ของ Lisp ให้เป็นโครงสร้างโค้ดแบบ Python และแทน S-expression ด้วยลิสต์ของ Python

    • Lisp ย่อมาจาก List Processing และใช้โครงสร้างข้อมูลเพียงแบบเดียวคือลิสต์

การอิมพลีเมนต์ครั้งแรก

  • ใช้ฟังก์ชันพื้นฐานของลิสต์ใน Python เพื่ออิมพลีเมนต์การดำเนินการพื้นฐานของ Lisp

    • atom(x): ตรวจว่า x เป็นลิสต์หรือไม่
    • eq(x,y): ตรวจว่า x และ y เท่ากันหรือไม่
    • car(x): คืนค่าองค์ประกอบแรกของลิสต์
    • cdr(x): คืนค่าส่วนที่เหลือของลิสต์
    • cons(x,y): เพิ่มอะตอมเข้าไปในลิสต์
    • append(x,y): รวมลิสต์สองอันเข้าด้วยกัน
  • แม้จะละเลยองค์ประกอบพื้นฐานบางส่วนของการเรียกซ้ำไป แต่ก็สามารถใช้ความช่วยเหลือจาก Llama3-70b เพื่ออิมพลีเมนต์อินเทอร์พรีเตอร์สำหรับบางส่วนของโค้ด "Lisp in Lisp" ได้อย่างรวดเร็ว

การอิมพลีเมนต์ครั้งที่สอง

  • ในการอิมพลีเมนต์ครั้งแรกยังไม่มีความสามารถเรื่อง lambda

    • lambda เป็นวิธีหลักในการนิยามและเรียกใช้ฟังก์ชันใน Lisp
    • หากไม่มี lambda ก็ไม่สามารถอิมพลีเมนต์ recursion ได้ และหากไม่มี recursion ก็จะไม่ Turing-complete
  • การอิมพลีเมนต์ lambda ต้องมีองค์ประกอบพื้นฐาน assoc(x,y) และ pairlis(x,y)

    • assoc(x,y) คือการ lookup พจนานุกรมแบบ key/value โดยใช้ association list
    • pairlis(x,y) มีความหมายเหมือนกับ zip(x,y) ของ Python
  • Lisp ไม่มี loop จึงต้องใช้ recursion แม้แต่กับการค้นหาเชิงเส้นอย่างง่าย

    • แต่ใน Python สามารถแปลงได้อย่างสวยงามด้วย list comprehension
    • เช่นเดียวกันกับ evcon และ evlis ที่แปลงเป็น loop ได้
  • เดิมทีฟังก์ชัน eval ใน Lisp รับอาร์กิวเมนต์สองตัว

    • ตัวแรกคือ expression (s-exp) และตัวที่สองคือ environment ซึ่งเป็นลิสต์ key/value
    • environment ใช้เก็บการผูกตัวแปรของ LAMBDA
    • ใช้เทคนิค dynamic scoping

ความเห็นของ GN⁺

  • นี่เป็นความพยายามที่น่าสนใจในการเลียนแบบคุณสมบัติ homoiconicity ของ Lisp ด้วย Python แต่ก็ดูเหมือนจะมีข้อจำกัดในการถ่ายทอดลักษณะเฉพาะของ Lisp ได้อย่างสมบูรณ์ หากอยากสัมผัสเสน่ห์ของ Lisp จริง ๆ การเรียนรู้ Lisp โดยตรงน่าจะดีที่สุด

  • การอิมพลีเมนต์ฟีเจอร์ทรงพลังของ Lisp เช่น lambda function และ dynamic scoping ด้วย Python นั้นน่าประทับใจ แต่ก็ดูเหมือนยังมีข้อจำกัดมากหากจะนำไปใช้กับโปรเจกต์จริง อย่างไรก็ตาม สำหรับการศึกษาและการวิจัยก็น่าจะมีคุณค่า

  • ความพยายามแบบนี้อาจเป็นจุดเริ่มต้นให้ได้คิดลึกขึ้นถึงธรรมชาติของภาษาโปรแกรมมิงเอง ไม่ใช่มองแค่ไวยากรณ์หรือการอิมพลีเมนต์ของภาษา แต่รวมถึงมุมมองในเชิง programming paradigm ด้วย

  • การเรียนรู้ภาษาตระกูล Lisp อาจช่วยให้เข้าใจ functional programming และ meta-programming ได้ลึกขึ้น และก็น่าสนใจที่จะลองดูภาษาตระกูล Lisp สมัยใหม่อย่าง Scheme, Clojure และ Racket ด้วย

1 ความคิดเห็น

 
kayws426 2024-05-13

ภาษาถิ่นของ Lisp ที่ฝังอยู่ใน Python
https://hylang.org/