• Tcl/Tk เป็นชุดเครื่องมือภายใต้ไลเซนส์ BSD ที่สามารถสร้างทั้ง CLI และ GUI แบบเนทีฟบน Windows, Linux และ macOS ได้ พร้อมรองรับอีเวนต์และ I/O แบบไม่บล็อก รวมถึงเธรดที่แยกจากกัน
  • Tcl เป็น ภาษาที่มีคำสั่งเป็นศูนย์กลาง โดยตีความคำแรกเป็นคำสั่ง และจัดการโค้ดกับข้อมูลในรูปแบบสตริง ส่วน Tk ทำ abstraction ให้ UI ของแต่ละระบบปฏิบัติการผ่านวิดเจ็ตและอีเวนต์
  • Tcl/Tk 9.0 ที่เปิดตัวเมื่อวันที่ 13 พฤศจิกายน 2025 เพิ่มการรองรับ 64 บิต, Unicode เต็มรูปแบบ, การเข้ารหัสที่เข้มงวด, การแพ็กเกจเป็นไฟล์เดียวด้วย ZipFS, SVG, DPI ความละเอียดสูง และ Dark Mode แต่มีการเปลี่ยนแปลงด้านความเข้ากันได้สำหรับโค้ดเดิมบางส่วน
  • ถูกใช้งานระยะยาวใน git gui, เครื่องมือ FPGA/EDA, Cisco IOS, สภาพแวดล้อมปฏิบัติการของ ESA, การบิลด์และทดสอบ SQLite, แอป Decent Espresso ฯลฯ และมีกรณีที่สคริปต์จากทศวรรษ 1990 ยังรันได้บนเวอร์ชันล่าสุด
  • เหมาะกับ UI แบบอิงอีเวนต์, งานอัตโนมัติ, I/O, DSL และการประสานงานโปรเซสเนทีฟในฐานะ ภาษาเชื่อมประสาน มากกว่าการคำนวณเชิงตัวเลขขนาดใหญ่ โดยสามารถมอบงานคำนวณให้คอมโพเนนต์ภายนอกอย่าง C, C# หรือ Python ได้

เหตุผลที่เลือก Tcl/Tk

  • Tcl/Tk สามารถจัดสภาพแวดล้อมได้ในขนาดประมาณ ไม่เกิน 100MB แม้รวมแพ็กเกจทั่วไป และสร้างแอปไฟล์เดี่ยวขนาดเล็กสำหรับแต่ละแพลตฟอร์มที่รองรับ รวมถึงเว็บแอปได้
  • ไลเซนส์ BSD อนุญาตให้แก้ไข แจกจ่ายซ้ำ และขายทั้งหมดหรือบางส่วนได้ โดยชุมชน Tcl ดูแลคอร์และรีลีสต่าง ๆ
  • ตัวเลือก GUI อื่น ๆ ที่พิจารณามีข้อจำกัดดังนี้
    • AutoHotkey v2 เหมาะกับเครื่องมือ Windows ขนาดเล็ก แต่เป็น Windows เท่านั้น และไม่สามารถรับประกันการเรียกแบบเนทีฟบน Wine ได้
    • C# WinForms ผูกกับ Windows API ส่วน MAUI และ Avalonia มี dependency ขนาดใหญ่ และทำให้การพัฒนาขนาดเล็กที่ไม่ใช่องค์กรยุ่งยาก
    • เว็บแอปโลคัลแบบ Electron ต้องจัดการการสื่อสารระหว่าง frontend/backend, port conflict และความปลอดภัย อีกทั้งแม้แต่เบราว์เซอร์เปล่า ๆ ก็อาจใช้พื้นที่เกิน 100MB
    • หน้าต่างแบบง่ายที่สร้างด้วย Fyne/Gio ของ Go มี dependency ทางอ้อมราว 40,000 รายการ และ static binary ขนาดเกิน 30MB อีกทั้งดูไม่เหมือนแอปเนทีฟ
    • Qt มีความซับซ้อนจาก MOC, signal/slot ที่ข้ามขอบเขตเนทีฟ และโครงสร้างไลเซนส์ GPL/LGPL/เชิงพาณิชย์
  • เฟรมเวิร์ก GUI สมัยใหม่จำนวนมากวาดลงบนแคนวาสโดยตรงแทนที่จะใช้ UI API ของระบบปฏิบัติการ และมักผูกสภาพแวดล้อมรันไทม์ทั้งชุดตาม OS/CPU ทำให้ได้รูปลักษณ์แบบเนทีฟได้ยาก

Tcl ที่ออกแบบมาเป็นภาษาเชื่อมประสาน

  • Tcl ที่ John Ousterhout เปิดตัวในปี 1990 ถูกออกแบบให้เป็น กาวเชิงสถาปัตยกรรม สำหรับเชื่อมโค้ดระดับต่ำประสิทธิภาพสูงกับเลเยอร์ตรรกะที่มนุษย์อ่านได้
    • Bridge: เชื่อมโค้ดอย่าง C++ หรือ Rust กับ UI ระดับสูง
    • Orchestrate: ควบคุมการไหลของข้อมูลระหว่างโปรแกรมและโมดูล
    • Wrap: เปิดเผยงานภายในที่ซับซ้อนให้ใช้งานผ่านคำสั่งสคริปต์แบบง่าย
  • Tk เป็นชุดเครื่องมือ GUI ข้ามแพลตฟอร์มที่เสริมการโต้ตอบผ่าน command line ของ Tcl และสามารถโหลดได้ด้วย package require Tk
  • คอร์ C ขนาดเล็กของ Tcl รองรับ Windows, Linux, macOS รวมถึง ARM, x86 และ RISC-V
    • บน Android สามารถใช้ Termux สำหรับ CLI และ AndroWish สำหรับ GUI ได้
  • Ousterhout ได้รับ ACM Software System Award ในปี 1997 จากผลงานการพัฒนาระบบซอฟต์แวร์ที่ส่งอิทธิพลอย่างต่อเนื่อง

กรณีใช้งานในอุตสาหกรรมระยะยาว

  • Tcl ถูกใช้งานมาราว 40 ปีในสภาพแวดล้อมที่ความน่าเชื่อถือ ความเข้ากันได้ย้อนหลัง และการพอร์ตมีความสำคัญ
    • git gui และ gitk ที่รวมอยู่ใน Git
    • ภาษาอัตโนมัติของเครื่องมือออกแบบ FPGA/ชิป เช่น Xilinx, Altera, Cadence
    • Cisco IOS Embedded Event Manager
    • GUI ภายในสำหรับ simulation farm และ hardware tester ของ Intel, NVIDIA, AMD
    • Calibre และ Virtuoso ของ Siemens EDA
    • สภาพแวดล้อมปฏิบัติการ ESTEC/ESOC ของ ESA
  • เครื่องมือ Tcl/Tk ตัวเดียวกันสามารถรันได้ตั้งแต่เทอร์มินัลของโรงไฟฟ้านิวเคลียร์ไปจนถึง Raspberry Pi โดยไม่ต้องคอมไพล์ใหม่
  • SQLite เริ่มต้นจากการเป็นส่วนขยายของ Tcl และการทดสอบครึ่งหนึ่งเขียนด้วย Tcl
    • Tcl ยังทำหน้าที่เป็น “assembler” ที่ post-process ไฟล์อินพุต C กว่า 125 ไฟล์ เพื่อสร้างซอร์สสุดท้ายของ SQLite มากกว่า 200,000 บรรทัด

องค์ประกอบการติดตั้งและวิธีรัน

  • การติดตั้งทั่วไปประกอบด้วยคอมโพเนนต์ต่อไปนี้
    • tclsh: อินเทอร์พรีเตอร์ CLI
    • wish: เชลล์ GUI ที่รวม Tk และ event loop
    • Tcllib·Tklib: ไลบรารี เช่น http, csv, json, aes, tooltip, dateentry
    • แพ็กเกจส่วนขยาย เช่น Thread, TLS, drag and drop
  • หากรันโดยไม่มีอาร์กิวเมนต์ จะเปิด REPL ซึ่งสามารถป้อนคำสั่ง วางสคริปต์ และรันไฟล์ผ่าน source ได้
  • หากส่งไฟล์เข้าไป เช่น tclsh myscript.tcl หรือ wish app.tkapp จะรันในโหมด batch แบบไม่โต้ตอบ
  • wish บน Windows เป็นแอปพลิเคชัน GUI จึงใช้ Tk Console แทนคอนโซลจริง และหาก UI thread ถูกบล็อก เอาต์พุตก็อาจดูเหมือนหยุดไปด้วย
  • สำหรับการเรียนรู้ แนะนำให้ใช้ tclsh ซึ่งให้ standard input/output บนทุกแพลตฟอร์มและยังสามารถโหลด Tk ได้

ไวยากรณ์ของ Tcl ที่มีคำสั่งเป็นศูนย์กลาง

  • ซอร์ส Tcl ประกอบด้วยคำที่คั่นด้วยช่องว่าง โดย คำแรกเป็นคำสั่งเสมอ และคำที่เหลือเป็นอาร์กิวเมนต์
  • องค์ประกอบไวยากรณ์หลักมีดังนี้
    • set: ตั้งค่าหรืออ่านค่าตัวแปร
    • $name: แทนที่ด้วยค่าของตัวแปร
    • proc: กำหนด procedure ที่ทำงานเป็นคำสั่งใหม่
    • [...]: รันสคริปต์ภายในและแทนที่ด้วยผลลัพธ์
    • {...}: รวมเป็นอาร์กิวเมนต์เดียวโดยไม่ทำการแทนที่
    • "...": รวมเป็นอาร์กิวเมนต์เดียว แต่ทำการแทนที่ $, [], \
    • {*}: ขยาย list เป็นหลายอาร์กิวเมนต์
    • ::: ระบุพาธ global/namespace
    • การขึ้นบรรทัดใหม่และ ;: แยกคำสั่ง
  • ใน string range "Tcl Programming" 0 2 นั้น string เป็น ensemble ที่ dispatch ไปยังคำสั่งย่อย range และคืนค่า Tcl
  • if, while, return ก็เป็นคำสั่งทั่วไป ไม่ใช่ reserved keyword
    • while ประเมินสตริงเงื่อนไขและเนื้อหาซ้ำ ๆ
    • เมื่อใช้ uplevel สามารถสร้าง control statement ที่ผู้ใช้กำหนดเองอย่าง repeat ... until|while ... ได้
    • return ส่ง completion code ได้แก่ TCL_OK, TCL_ERROR, TCL_RETURN, TCL_BREAK, TCL_CONTINUE

Homoiconicity และการแทนที่อย่างปลอดภัย

  • ใน Tcl โค้ดและข้อมูลล้วนเป็นสตริงที่ประกอบด้วยคำ จึงสามารถตีความค่าเดียวกันเป็น list, ข้อมูล หรือคำสั่งที่รันได้
  • เมื่อขยาย list อย่าง {*}$userinput องค์ประกอบแรกจะกลายเป็นคำสั่ง และองค์ประกอบที่เหลือเป็นอาร์กิวเมนต์ ดังนั้นหากไม่ครอบอาร์กิวเมนต์ที่มีช่องว่างอย่างถูกต้อง อาจเกิดปัญหาอย่างข้อผิดพลาดชื่อ channel ได้
  • Homoiconicity นี้ทำให้การขยาย DSL และ control statement ทำได้ง่าย แต่ก็สร้างภาระด้านความถูกต้องสมบูรณ์และความปลอดภัย เพราะข้อมูลอาจกลายเป็นโค้ดที่ถูกเรียกใช้ได้
  • ควรประกอบ callback ด้วย [list command $arg] เพื่อรักษาขอบเขตของอาร์กิวเมนต์ที่มีช่องว่างและอักขระพิเศษ
  • expression ของ expr และ if ควรครอบด้วย {...} เสมอ เพื่อป้องกันการแทนที่ซ้ำและ command injection รวมถึงให้ได้รับการ optimize เป็น bytecode
  • Safe Interpreter จะบล็อกการเข้าถึง filesystem, socket และไลบรารีภายนอกโดยค่าเริ่มต้น และเปิดเผยเฉพาะฟังก์ชันที่อนุญาตผ่าน interp alias

การเปลี่ยนแปลงใน Tcl/Tk 9.0

  • Tcl/Tk Core Development Team เปิดตัวเวอร์ชัน 9.0 เมื่อวันที่ 13 พฤศจิกายน 2025 หลังจาก Tcl 8.6 เป็นเวลา 12 ปี
  • การเปลี่ยนแปลงหลักมีดังนี้
    • ย้ายไปเป็น 64 บิตอย่างสมบูรณ์ และรองรับ Unicode code point ทั้งหมด
    • ZipFS สำหรับเมานต์ ZIP เป็นระบบไฟล์เสมือน
    • Tk รองรับ SVG, DPI ความละเอียดสูง, การแจ้งเตือนของระบบ และ Dark Mode บน Windows·macOS
    • โปรไฟล์เริ่มต้น strict ที่แจ้งข้อผิดพลาดทันทีเมื่อ encoding ไม่ตรงกัน
  • มีการเปลี่ยนแปลงด้านความเข้ากันได้ด้วย
    • การเปลี่ยนแปลงขนาด pointer อาจทำให้สคริปต์ที่มีโค้ด C ของ critcl หยุดทำงานได้
    • 010 ใน Tcl 8.x คือเลขฐานแปดค่า 8 แต่ใน Tcl 9 คือเลขฐานสิบค่า 10 และเลขฐานแปดใช้ prefix 0o
    • ไม่ลบ UTF-8 BOM U+FEFF โดยอัตโนมัติ หากจำเป็นต้องตัดออกอย่างชัดเจน
  • Tcl 8.6 ยังใช้พัฒนา CLI·GUI ทั่วไปได้ แต่สำหรับโปรเจกต์ใหม่แนะนำให้ใช้ 9.0 ซึ่งมีความปลอดภัยและการปรับปรุง UI
  • อิมพลีเมนเทชันขนาดเล็กมี Jim TCL ขนาดราว 100~200kB และ Picol ที่เป็นโค้ด C น้อยกว่า 1,000 บรรทัด

วิดเจ็ต Tk และรูปลักษณ์สมัยใหม่

  • Tk ไม่ได้เปิดเผย Win32, X11, Cocoa โดยตรง แต่ abstract ผ่าน คำสั่งวิดเจ็ต และ event binding
  • Tk ยุคแรกทิ้งภาพจำว่าล้าสมัยเพราะวิดเจ็ตคลาสสิกสีเทาและเหลี่ยม แต่ ttk ให้วิดเจ็ตที่ใกล้เคียงธีมของระบบปฏิบัติการ
    • ธีมที่รวมมาโดยพื้นฐานคือ alt, default, clam, classic
    • แอปเก่าสามารถแทนที่วิดเจ็ตคลาสสิกด้วย ttk::treeview, ttk::notebook, ttk::progressbar เป็นต้น
  • mortgage calculator applet ปี 1996 ยังรันได้บน Tcl 9.0.3 และเวอร์ชันปรับให้ทันสมัยเพิ่ม grid, การตรวจสอบอินพุต, เงินดาวน์, การรองรับ DPI และ canvas แบบ responsive
    • ต้นฉบับมี 188 บรรทัดเมื่อไม่รวมคอมเมนต์และบรรทัดว่าง ส่วนเวอร์ชันปรับใหม่มีราว 250 บรรทัดรวมฟีเจอร์ใหม่
    • สคริปต์เดียวกันรันได้บน Windows 10, Linux Mint, แท็บเล็ต·โทรศัพท์ Android และ ARM SBC
  • Tcl/Tk 9.0 ขยายแทบจะเป็นสัดส่วนที่ 96 DPI·144 DPI บน Windows และควรใช้หน่วยสัมพัทธ์กับ padding มากกว่าพิกเซลคงที่
  • แนะนำให้เรียนรู้ลำดับชั้นวิดเจ็ต, path แบบใช้จุด, เลย์เอาต์ และอีเวนต์จาก TkDocs tutorial

Event loop และการเชื่อมโยงแบบหลวม

  • event loop ของ Tcl ประมวลผลเมาส์·คีย์บอร์ด, ไฟล์·channel และ callback ตามลำดับคิวในเธรดเดียว และจะเริ่มทำงานเบื้องหลังเมื่อโหลด Tk
  • treeview กับ scrollbar เป็นวิดเจ็ต sibling ที่ไม่ได้ครอบกันและกัน และแลกเปลี่ยน command prefix เพื่ออัปเดตตำแหน่งแบบสองทิศทาง
  • Tk สามารถส่ง virtual event อย่าง <<UI:Request:Submit>> พร้อม payload แบบ dict ไปยังวิดเจ็ตได้
  • EventManager ที่นำกลับมาใช้ซ้ำได้สามารถจัดการรายชื่อ subscriber ของแต่ละ event ด้วยพจนานุกรม และเรียก event generate เฉพาะกับวิดเจ็ตที่มีอยู่
    • มีบทบาทคล้าย C# Events/Delegates, JavaScript CustomEvent, Python PyPubSub·blinker
    • สามารถส่งผลการตรวจสอบไปยัง subscriber หลายตัว เช่น popup, inspector, ปุ่ม Send โดยไม่ต้องอ้างอิงกันโดยตรง
  • แม้ใน Tcl ล้วนก็สร้าง event manager ที่เรียก callback ของ subscriber ได้ และนำไปใช้กับแอนิเมชันคอนโซลแบบอิง tick ทุก 50ms หรือการเลื่อนหลาย canvas ให้ซิงก์กันได้
  • การออกแบบ event ที่ยึดข้อมูลเป็นศูนย์กลางเหมาะกับระบบแบบ MVC ที่แยก UI กับตรรกะ และสอดคล้องกับขั้นตอนเลือกเหตุการณ์·รวบรวมข้อมูล·ตัดสินกลยุทธ์·ดำเนินการ·ประเมินผลของ PIOSEE

การเชื่อมต่อกับ Python และโปรเซสภายนอก

  • tkinter ของ Python เป็น wrapper ของ Tk แต่ตัวอย่างเก่าและธีมเริ่มต้นอาจทำให้เกิดภาพจำว่า Tk เองล้าสมัย
    • หากต้องการรูปลักษณ์สมัยใหม่ ต้องใช้ from tkinter import ttk และ ttk.Label, ttk.Button เป็นต้นอย่างชัดเจน
  • แนะนำให้ใช้ Tk ผ่าน Tcl ซึ่งถูกออกแบบมาคู่กันตั้งแต่แรก และแยก Python เป็นชั้นประมวลผลข้อมูล
  • งาน Python แบบครั้งเดียวเชื่อมด้วย exec ส่วนงาน asynchronous ต่อเนื่องเชื่อมผ่าน pipe ด้วย open "|python3 -u script.py" r+
    • เมื่อใช้ non-blocking·line buffering และ fileevent GUI จะยังตอบสนองได้ขณะทำงาน NumPy·Pandas
  • หากเชื่อมต่อโปรเซสลูกแบบ native เช่น C# ด้วยวิธีเดียวกัน แม้โปรเซสคำนวณจะ crash หรือใช้ CPU ทั้งหมด โปรเซส UI ก็ยังถูกแยกออกจากกัน
  • EOF ของ pipe ก็เป็น readable event เช่นกัน ดังนั้นในฟังก์ชันจัดการต้องตรวจ [eof $pipe] เพื่อป้องกัน callback วนไม่รู้จบ

การแทนค่า โครงสร้างข้อมูล และประสิทธิภาพ

  • “Everything is a String” หมายความว่าค่าทุกค่ามี การแทนมาตรฐาน เป็นสตริง ไม่ได้หมายความว่าถูกเก็บเป็นสตริงเสมอไป
  • Tcl_Obj เป็นอ็อบเจกต์แบบ dual-ported ที่จัดการทั้งการแทนแบบสตริง UTF-8 และการแทนภายใน เช่น integer, list, dict, byte array
  • การสร้างการแทนภายในใหม่เมื่อชนิดที่ต้องการเปลี่ยนไปเรียกว่า shimmering
    • สำหรับ list ควรใช้คำสั่ง lappend·lindex ต่อเนื่อง, สำหรับ dict ใช้ dict, สำหรับไบนารีใช้ binary เพื่อลดต้นทุนการแปลงและความเสียหายของข้อมูล
    • สามารถวินิจฉัย object pointer และการแทนภายในด้วย tcl::unsupported::representation
  • Tcl ใช้ Copy-on-Write จึงไม่คัดลอกทันทีเมื่อกำหนดค่า แต่จะโคลนเมื่อมีการแก้ไขอ็อบเจกต์ที่แชร์อยู่จริง
  • ไบนารีอย่าง PNG ต้องตั้งค่า channel เป็น -translation binary และใช้ binary encode/decode เพื่อหลีกเลี่ยงการแปลง CR/LF และ UTF-8
  • dict set สร้างเส้นทางกลางให้อัตโนมัติ และสามารถแก้ไขค่าที่ซ้อนกันเหมือนตัวแปรท้องถิ่นด้วย dict with, dict update
    • คีย์ซ้ำจะถูกจัดการแบบ Last Writer Wins โดยเหลือค่าล่าสุดไว้
  • list เหมาะกับข้อมูลที่มีลำดับและโครงสร้างแบบเมทริกซ์ ส่วน dict เหมาะกับข้อมูล key-value ซ้อนทั่วไป

Array, namespace และ TclOO

  • namespace เป็นคอนเทนเนอร์แบบไดนามิกที่เก็บตัวแปรและคำสั่ง และสามารถสร้าง dispatcher อย่าง Logger log ได้ด้วย namespace ensemble
  • ตัวแปรและคำสั่งใช้ hash table แยกกัน จึงมีชื่อเดียวกันพร้อมกันได้ และตรวจสอบโครงสร้าง runtime ได้ด้วย info vars, info commands, info procs
  • Tcl Array คือ hash table แบบแบนที่ชี้ไปยังตัวแปรแต่ละตัว
    • เหมาะกับคอลเลกชันที่มีคีย์ไดนามิก เช่น สถานะ UI และสามารถ bind หรือ trace องค์ประกอบแต่ละตัวกับวิดเจ็ตได้
    • สำหรับ procedure ต้องส่งชื่อ array แล้วใช้ upvar เพื่อเชื่อม alias ไปยังต้นฉบับ
  • แนะนำให้ใช้ namespace สำหรับสถานะ global·singleton ที่มีคีย์คงที่ และใช้ array สำหรับคอลเลกชันคีย์ไดนามิก
  • TclOO ซึ่งรวมอยู่ใน core ตั้งแต่ Tcl 8.6 ให้ class, object, inheritance, constructor·destructor โดยอิง namespace และ command dispatch
    • object เป็นคำสั่งจริงอย่าง ::oo::Obj42 และเก็บสถานะไว้ใน namespace เฉพาะ
    • สามารถเปลี่ยน class ด้วย oo::define และเปลี่ยน object เฉพาะตัวขณะ runtime ด้วย oo::objdefine
    • mymethod สร้าง callback เมธอดของ object แบบครบถ้วนสำหรับส่งให้ after เป็นต้น
  • TclOO ไม่มี garbage collection จึงต้องลบ object อย่างชัดเจนด้วย $obj destroy
    • สามารถจัดการอายุการใช้งานด้วย try/finally หรือ managed_create แบบอิง variable trace
    • channel ก็ต้อง close และสามารถใช้ managed_channel เพื่อ cleanup อัตโนมัติเมื่อออกจาก scope
  • วิดเจ็ต Tk ก็ยังคงอยู่ในรูปคำสั่งเช่นกัน แต่เมื่อ destroy วิดเจ็ตแม่ วิดเจ็กลูกทั้งหมดจะถูกลบไปด้วย

โครูทีนและเธรด

  • โครูทีนของ Tcl เป็น stackful coroutine ที่รักษาสแตกการเรียกทั้งหมดไว้ และหลังจาก yield จะกลับมาทำงานต่อโดยคงตัวแปรภายในและตำแหน่งการทำงานเดิมไว้
  • เมื่อนำ after มารวมกับโครูทีน จะสามารถจัดการดาวน์โหลด, state machine, แอนิเมชัน และงานเครือข่ายภายใน event loop ได้แบบไม่บล็อก
    • CLI ล้วนต้องใช้ vwait เพื่อคงโปรเซสไว้ แต่แอป Tk มี window manager คอยรักษา event loop ให้
    • coroutine::util ของ tcllib มี wrapper ที่รับรู้โครูทีนสำหรับ socket, gets, read
  • โครูทีนใช้เธรด CPU เดียวร่วมกัน ดังนั้นหากมีการคำนวณยาว ๆ ทำงานอยู่ UI ทั้งหมดจะค้าง และควรแยกงานเหล่านี้ออกด้วยแพ็กเกจ Thread
  • Tcl Thread เป็นโมเดล shared-nothing ที่แต่ละเธรดมีอินเทอร์พรีเตอร์แยกจากกัน
    • ส่งข้อความด้วย thread::send และ TSV ให้ค่าที่แชร์ร่วมกันซึ่งป้องกันด้วย mutex
    • ช่องทาง (channel) โอนความเป็นเจ้าของได้ด้วย thread::transfer, detach, attach
  • เธรดที่ติดอยู่ในลูปไม่สิ้นสุดจะไม่กลับเข้าสู่ event queue จึงไม่สามารถบังคับปิดได้อย่างปลอดภัย
  • เมื่อสร้างเธรดย่อย 32 เธรดบน AMD 5950X หน่วยความจำเพิ่มจาก 24MB เป็น 44MB หรือใช้ราว 0.6MB ต่ออินเทอร์พรีเตอร์
  • การทำเธรดของ Tcl เป็นฟีเจอร์เพื่อการตอบสนองของ UI และการประสานงาน I/O มากกว่าการแข่งขันด้านประสิทธิภาพการคำนวณ
    • ในการทดสอบหารากที่สอง 100 ล้านครั้ง AoT C# ใช้ 0.24 วินาที ส่วน Tcl ใช้ 16.8 วินาที ต่างกันประมาณ 70 เท่า

แยกการคำนวณด้วย C·C#

  • critcl จะคอมไพล์โค้ด C·C++ ที่อยู่ในสคริปต์ Tcl เมื่อรันครั้งแรก แล้วเรียกใช้เป็นคำสั่งเนทีฟ
    • ระหว่างพัฒนาต้องมี gcc หรือ clang และหลังทำเสร็จสามารถพรีบิลด์เป็นแพ็กเกจ .dll·.so เพื่อแจกจ่ายได้
  • ส่วนที่เป็นคอขวดด้านประสิทธิภาพอย่าง Mandelbrot หรือ Fibonacci สามารถย้ายไปเขียนด้วย C ได้ แต่งานที่ต้องจัดการโครงสร้างหน่วยความจำ Tcl/C โดยตรงนั้นยุ่งยาก
  • อีกทางเลือกคือใช้ Tcl/Tk เป็น UI บาง ๆ แล้วมอบการคำนวณให้โปรเซสแยกต่างหาก ซึ่งเป็น Sidecar Pattern
  • BFlat คอมไพล์ C# เป็นไบนารีเนทีฟแบบ self-contained และรองรับ Windows·Linux·Android
    • CLI คำนวณตัวเลขพื้นฐานบน Windows อาจมีขนาดราว 900KB และหลังบีบอัดด้วย UPX อาจต่ำกว่า 500KB
    • เมื่อรวมกับอินเทอร์พรีเตอร์ Tcl ขนาดราว 3MB จะสามารถจัดแอปตามแพลตฟอร์มให้มีขนาดประมาณ 3~4MB ได้

ZipFS และการแจกจ่ายไฟล์เดียว

  • ก่อน Tcl 9 มีการใช้ Starpack ซึ่งนำ Starkit ไปแนบกับ Tclkit แต่ต้องพึ่งเครื่องมือแยกอย่าง Metakit และ SDX
  • ZipFS ของ Tcl 9 เมานต์ ZIP เป็นระบบไฟล์เสมือนแบบอ่านอย่างเดียวที่ //zipfs:/
  • Zipkit รวม tclsh·wish ที่ลิงก์แบบ static กับ ZIP ของแอป แล้วรัน main.tcl ตอนเริ่มต้น
    • มีเป้าหมายสำหรับ Windows x86/x86_64, macOS Intel·Apple Silicon, Linux x86_64/arm64/RISC-V 64 บิต และตระกูล Solaris
    • เพียงเปลี่ยนเทมเพลต Zipkit ก็สามารถทำ cross-packaging ไบนารีสำหรับ OS อื่นได้
  • ZipFS เริ่มจากการใช้งาน VFS ของ AndroWish ซึ่งต้องอ่านไฟล์ภายใน APK โดยตรง ก่อนถูกรวมเข้า Tcl core
  • หากรวม .dll·.so เฉพาะแพลตฟอร์มไว้ด้วย ต้องตรวจจับแพลตฟอร์มที่รันและเลือกส่วนขยายที่ถูกต้อง

AndroWish และ Decent Espresso

  • แอป DE1 ของ Decent Espresso ยังคงเป็นแอป Tcl/Tk ที่รันบน AndroWish ณ เดือนเมษายน 2026
  • แท็บเล็ตไม่ได้เป็นไคลเอนต์ของเซิร์ฟเวอร์ระยะไกล แต่ใช้ สถาปัตยกรรม local-first ที่ทำงานเป็น peer ของเครื่องชงกาแฟ
  • AndroWish แมปคำสั่งวาดของ Tk เป็น texture ของ SDL2 จึงจัดการการแสดงผลความถี่สูงได้แม้บนแท็บเล็ต Android สเปกต่ำ
    • ส่วนขยาย borg ให้ Bluetooth, การแจ้งเตือน, การสั่น, เสียง, ตำแหน่ง และอีเวนต์สถานะของ Android
    • ณ เดือนพฤษภาคม 2026 รองรับเฉพาะ Tcl/Tk 8.6 จึงใช้คำสั่งเฉพาะ Tcl 9 ไม่ได้
  • AndroWish SDK สร้าง APK ที่รวมสคริปต์ไว้ และหากลบส่วนขยายที่ไม่จำเป็นออก ขนาดประมาณ 30MB จะลดเหลือ 4~10MB ได้
  • undrowish เป็นอินเทอร์พรีเตอร์ไฟล์เดียวสำหรับทดสอบสภาพแวดล้อม SDL เดียวกันบน Windows·Linux แต่ไม่รวม Android borg
  • สามารถใช้ tkconclient เชื่อมต่อระยะไกลจาก PC ไปยังอินเทอร์พรีเตอร์ Android ได้ แต่เพราะไม่มีรหัสผ่านจึงควรใช้เฉพาะระหว่างพัฒนา
  • Tk มีข้อจำกัดด้านการปรับภาพ raster อัตโนมัติตามความละเอียด Android และ UI เต็มจอแบบสัมผัส ทำให้ Decent Espresso ต้องสร้าง UI แบบสกินเอง

Wapp, DSL และ sandbox

  • Wapp เป็นเว็บเฟรมเวิร์ก Tcl แบบเน้นไฟล์เดียวที่สร้างโดย D. Richard Hipp
    • รองรับเซิร์ฟเวอร์ซ็อกเก็ตในตัว, CGI·SCGI และจัดการ URI decoding กับการทำความสะอาดพารามิเตอร์โดยพื้นฐาน
    • ใช้ในแอป checklist ที่จัดการขั้นตอนการปล่อย SQLite และเว็บ UI ของ Fossil
    • หากรวม htmx กับ CSS ปริมาณเล็กน้อย จะสร้างเว็บแอปที่เน้นโปรซีเยอร์ Tcl ได้โดยไม่ต้องใช้ JavaScript
  • หากการเข้าถึงจากระยะไกล·มือถือเป็นสิ่งจำเป็น แนะนำ Wapp ส่วนเครื่องมือท้องถิ่นแนะนำ Tk ที่ผสานกับระบบปฏิบัติการโดยตรง
  • Tcl เหมาะกับการสร้าง DSL เพราะแม้แต่ลูปและเงื่อนไขก็เป็นคำสั่ง
    • ใช้ unknown, uplevel, upvar เพื่อสร้างคำสั่งทางธุรกิจอย่าง checkout 1000 USD ได้
    • สามารถสร้างสภาพแวดล้อมสคริปต์แบบจำกัดสำหรับธนาคาร·EDA โดยเปิดเผยเฉพาะคำสั่งที่อนุญาตใน Safe Interpreter
  • ยังสามารถสร้างคำสั่งแบบมาโครเพื่อสร้างขั้นตอน post-processing ของสตริงหรือ flow การทำงานเฉพาะแอปพลิเคชันได้

ฟังก์ชันระบบปฏิบัติการแบบเนทีฟ

  • Tcl/Tk เรียกใช้ได้ทั้งคำสั่งร่วมและ API เฉพาะแพลตฟอร์มผ่านส่วนขยาย
  • TWAPI บน Windows ให้ API ระดับต่ำที่ใกล้เคียง Windows SDK และอินเทอร์เฟซอำนวยความสะดวก
    • ใช้ twapi::shell_execute -verb runas เพื่อขอ elevation สิทธิ์ UAC ได้
    • เข้าถึงเวลา creation·modification ของไฟล์, global hotkey, service และฟังก์ชันของ Windows ได้
  • ในกรณีเครื่องมือช่วย Adobe DNG Converter หลังแปลง RAW รุ่นใหม่เป็น DNG ที่เข้ากันได้กับ CS6 แล้ว จะใช้ TWAPI กู้คืนเวลา creation·modification ของไฟล์ต้นฉบับ
    • Tcl ล้วนจัดการได้เฉพาะเวลา modification·access จึงต้องใช้ TWAPI เพื่อกู้คืนเวลา creation ของ Windows

ข้อจำกัดและวินัยในการพัฒนา

  • Tcl วางภาระด้านความถูกต้องไว้ที่วินัยของนักพัฒนามากกว่าคอมไพเลอร์
    • หากเข้าใจความต่างของการแทนที่ระหว่าง {} กับ "" ผิด อาจเกิดการแทนที่ซ้ำและช่องโหว่ความปลอดภัย
    • dict get, expr, format ที่ซ้อนกันควรแยกเป็นตัวแปรทีละขั้นเพื่อให้อ่านง่าย
    • หากนิยามภาษาใหม่มากเกินไป อาจกลายเป็นระบบคำสั่งกำหนดเองที่ดูแลรักษายาก
  • Tcl แยกความต่างระหว่างการมีอยู่ของตัวแปรกับสตริงว่างแทน null และตรวจสอบด้วย info exists
    • หากใส่สตริงว่างในนิพจน์คณิตศาสตร์ จะไม่แปลงเป็น 0 หรือ NaN อัตโนมัติ แต่จะเกิดข้อผิดพลาด
  • ไม่เหมาะกับ 3D·เสียงแบบเรียลไทม์และการคำนวณเมทริกซ์ขนาดใหญ่
    • Tcl3D·Canvas3d และคำสั่งเสียงภายนอกใช้ได้ แต่ไม่ใช่กรณีใช้งานหลัก
    • หากประมวลผลเมทริกซ์ 1GB เป็นสตริง·ลิสต์ ค่าใช้จ่ายในการจัดการอ็อบเจ็กต์จะสูง จึงเหมาะกับไลบรารี C หรือโปรเซสคำนวณแยกมากกว่า
  • จุดแข็งของ Tcl คือการประสานงานด้วยโครูทีน·เธรด, I/O และอีเวนต์, ชั้นการแสดงผล Tk·CLI, การทดสอบและอัตโนมัติ

แพ็กเกจและสภาพแวดล้อมการพัฒนา

  • Tcl ไม่มีตัวจัดการแพ็กเกจกลางแบบสากลที่เทียบได้กับ npm หรือ pip และ teacup/teapot ของ ActiveTcl ส่วนใหญ่กลายเป็นของเก่าไปแล้ว
  • ดิสทริบิวชันแบบ Batteries Included มาพร้อมแพ็กเกจที่ผ่านการตรวจสอบแล้ว
    • Magicsplat ให้บริการแพ็กเกจ Tcl/Tk 9 ที่คัดสรรมา โดยเน้น Windows เป็นหลัก
    • BAWT เป็นเฟรมเวิร์กบิลด์แนว maximalist สำหรับสร้างดิสทริบิวชันที่รวมส่วนขยายสำหรับหลายแพลตฟอร์มและหลาย CPU
    • ขึ้นอยู่กับการตั้งค่า สามารถรวมแพ็กเกจหลักของอีโคซิสเต็มไว้ได้ในขนาดประมาณ 35MB
  • การไม่มีตัวจัดการกลางไม่ได้ทำให้ปลอดภัยขึ้นโดยอัตโนมัติ แต่มีข้อดีคือสามารถล็อก dependency ทั้งหมดแล้ววิเคราะห์เพียงครั้งเดียวได้
  • Tcl สร้างคำสั่งแบบไดนามิก จึงทำให้การวิเคราะห์แบบสแตติกและ autocomplete ทำได้ยาก และ Nagelfar ก็ไม่สามารถตรวจสอบคำสั่งที่ไม่รู้จักหรือการนิยามใหม่ตอนรันไทม์ได้อย่างสมบูรณ์
  • ใน VSCode/VSCodium สามารถใช้ Tcl by bitwisecook, Tcl Navigation and Tools, Code Runner ได้

การติดตั้งตามแพลตฟอร์ม

  • บน Windows หากติดตั้ง Magicsplat Tcl/Tk แบบทั่วทั้งระบบ จะสามารถตั้งค่า PATH และการเชื่อมโยงไฟล์ .tclapp/.tkapp ได้
  • บนตระกูล Debian/Ubuntu สามารถติดตั้ง Tcl, Tk, SQLite, TLS, image และ Thread ได้ด้วยแพ็กเกจต่อไปนี้
    • sudo apt-get install tcl tk libsqlite3-tcl sqlite-tcl tcltls tcllib libtk-img tcl-thread
  • repository ของ Linux LTS หลายรายการมี Tcl 8.6 ให้ใช้งาน และบิลด์ที่รวมส่วนขยาย Tcl 9 มีให้ที่ tcl-builds-with-libxft
  • มีกรณีที่ Tk ทำงานได้ไม่เฉพาะบน X11 เท่านั้น แต่ยังรวมถึงสภาพแวดล้อม Wayland อย่าง Zorin OS 18 ด้วย
  • Tcl 8.5 ที่มากับ macOS โดยพื้นฐานมีไว้เพื่อความเข้ากันได้กับ legacy จึงแนะนำให้หลีกเลี่ยงสำหรับการพัฒนา Tcl/Tk สมัยใหม่
    • สามารถติดตั้ง Tcl/Tk 9 ผ่าน Homebrew, MacPorts หรือบิลด์ BAWT แบบทดลองได้
    • บน Apple Silicon ควรวาง /opt/homebrew/opt/tcl-tk/bin ไว้ด้านหน้าของ PATH เพื่อให้มีลำดับความสำคัญเหนือ Tcl ของระบบ

แหล่งเรียนรู้และการประเมินโดยสรุป

  • The Tcl 9 Programming Language เป็นแหล่งข้อมูลขั้นสูงที่ลงลึก Tcl 9 ล้วน ๆ และเพื่อให้เข้าใจฟีเจอร์ทั้งหมด แนะนำให้อ่านซ้ำและไล่ตามตัวอย่างด้วยตนเอง
  • TkDocs ครอบคลุม Tk สมัยใหม่, grid, event loop และเทคนิคเก่า ๆ ที่ควรหลีกเลี่ยง
  • ไม่แนะนำเอกสารของ Tutorialspoint เพราะมีวิธีติดตั้งที่ล้าสมัยและแนวปฏิบัติอย่าง expr ที่ไม่ใส่วงเล็บปีกกา
  • REPL ของ tclsh และ wish จะแสดงวิธีใช้งานเมื่อป้อนอาร์กิวเมนต์ผิด จึงใช้เป็นเครื่องมือเรียนรู้สำหรับทดลองควบคู่กับเอกสารได้
  • Tcl/Tk ไม่ใช่อีโคซิสเต็มที่กำลังเป็นกระแสหรือมีชุมชนขนาดใหญ่ แต่ยังคงเป็นชุดเครื่องมืออเนกประสงค์ที่ให้ความสำคัญกับ ความเข้ากันได้ระยะยาวและความสม่ำเสมอ ในทีมขนาดเล็กและอุตสาหกรรมที่เป็น mission-critical
  • เหมาะเมื่อคุณต้องการ ‘boring technology’ ที่ทำงานได้ยาวนานหลายสิบปีมากกว่าสแต็กที่เปลี่ยนเร็ว และต้องการเลเยอร์ CLI/GUI/automation/orchestration มากกว่าเครื่องมือคำนวณ

ยังไม่มีความคิดเห็น

ยังไม่มีความคิดเห็น