ภาษาแม่แบบดั้งเดิมทั้งเจ็ดของการเขียนโปรแกรม (2022)
(madhadron.com)- ความแตกต่างของ ชุดรูปแบบพื้นฐาน สำคัญกว่าความต่างของไวยากรณ์รายภาษา และภาษาโปรแกรมแบ่งได้เป็น ภาษาแม่แบบดั้งเดิม 7 แบบ ตามวิธีการทำซ้ำ การเรียกซ้ำ และการประกอบโปรแกรม
- ALGOL, Lisp, ML, Self, Forth, APL, Prolog คือหมวดหลัก โดยใช้ภาษาตัวแทนของแต่ละสายเป็นเสมือนตัวอย่างอ้างอิงเพื่อตัดสินสายสืบทอดของภาษาอื่น
- ภาษาใหม่ที่ใช้ภาษาแม่แบบดั้งเดิมที่คุ้นเคยร่วมกันจะเรียนรู้ได้ง่าย แต่เมื่อย้ายไปยังแม่แบบที่ไม่คุ้นเคย จะต้องใช้ เส้นทางความคิดแบบใหม่ และเวลาเรียนรู้อย่างมาก
- ALGOL เด่นที่การจัดองค์ประกอบของฟังก์ชันโดยมีการกำหนดค่า เงื่อนไข และลูปเป็นศูนย์กลาง, Lisp เด่นที่ มาโครและโค้ดแบบลิสต์, ML เด่นที่ฟังก์ชันชั้นหนึ่งและการเรียกซ้ำ, Self เด่นที่อ็อบเจ็กต์แบบส่งข้อความ, Forth เด่นที่ไวยากรณ์แบบสแตก, APL เด่นที่อาร์เรย์ n มิติ, และ Prolog เด่นที่โครงสร้างแบบข้อเท็จจริงและการค้นหา
- สำหรับโปรแกรมเมอร์ทุกคน การชำนาญ ภาษาในสาย ALGOL ควรเป็นลำดับแรก จากนั้นเรียน SQL แล้วค่อย ๆ เรียนภาษาแม่แบบดั้งเดิมที่ไม่คุ้นเคยเพิ่มเติมอย่างต่อเนื่อง ซึ่งให้ผลดีในระยะยาว
ภาษาแม่แบบดั้งเดิมทั้งเจ็ดของการเขียนโปรแกรม
- เวลาเลือกภาษาโปรแกรม การเรียนรู้ รูปแบบพื้นฐาน สำคัญกว่าความต่างของไวยากรณ์รายภาษา และในบรรดาภาษาที่อยู่ในสายใกล้เคียงกัน โครงสร้างพื้นฐานอย่างการวนดูอาร์เรย์หรือการวนดูชุดค่าผสมก็มักมีรูปแบบแทบไม่ต่างกัน
- กลุ่มภาษาที่ต่างกันมีวิธีทำซ้ำ การเรียกซ้ำ และการจัดองค์ประกอบโปรแกรมที่ต่างกันมาก และ ชุดรูปแบบพื้นฐาน เหล่านี้เองที่ก่อให้เกิดภาษาแม่แบบดั้งเดิมที่แตกต่างกัน
- การเรียนภาษาใหม่ที่ใช้ภาษาแม่แบบดั้งเดิมเดียวกับที่คุ้นเคยเป็นการย้ายที่ค่อนข้างง่าย แต่การย้ายไปยังภาษาแม่แบบดั้งเดิมที่ไม่คุ้นเคยต้องใช้เวลาอย่างมากและต้องสร้างเส้นทางความคิดใหม่
- ภาษาแม่แบบดั้งเดิมที่วงการซอฟต์แวร์รับรู้มีอยู่เจ็ดแบบคือ ALGOL, Lisp, ML, Self, Forth, APL, Prolog
- ภาษาแม่แบบดั้งเดิมแต่ละแบบถูกจัดหมวดโดยยึดภาษาตัวแทนเฉพาะเป็นเหมือนตัวอย่างมาตรฐาน แล้วเปรียบเทียบภาษาอื่นกับตัวอย่างนั้นเพื่อพิจารณาสายสืบทอด
-
ALGOL
- โปรแกรมประกอบด้วยลำดับของ การกำหนดค่า คำสั่งเงื่อนไข และลูป และถูกจัดเป็นหน่วยของฟังก์ชัน
- หลายภาษาเพิ่มระบบโมดูล วิธีนิยามชนิดข้อมูลใหม่ พหุสัณฐาน และโครงสร้างควบคุมทางเลือกอย่างข้อยกเว้นหรือโครูทีนเข้าไปบนพื้นฐานนี้
- ภาษาโปรแกรมส่วนใหญ่ที่ใช้อย่างกว้างขวางในปัจจุบันอยู่ในสายของภาษาแม่แบบดั้งเดิมนี้
- ตัว ALGOL เองรวมถึง ALGOL 58, ALGOL 60, ALGOL W, ALGOL 68
- Assembly language, Fortran, C, C++, Python, Java, C#, Ruby, Pascal, JavaScript และ Ada เชื่อมโยงอยู่กับสายนี้
- เป็นภาษาแม่แบบดั้งเดิมที่เก่าแก่ที่สุด โดยมีเชื้อสายย้อนกลับไปได้ถึงการทำให้โปรแกรมสำหรับเครื่องวิเคราะห์ของ Babbage เป็นรูปแบบทางการโดย Ada Lovelace
- ภาษาเครื่องและแอสเซมบลีของคอมพิวเตอร์สถาปัตยกรรม Eckert-Mauchly ที่ต่อเนื่องไปสู่ EDVAC และ Univac รุ่นแรก ตลอดจนความพยายามสร้างภาษาระดับสูงยุคต้นตั้งแต่ A-0 ของ Grace Hopper ไปจนถึง Fortran และ COBOL ล้วนอยู่ในรูปแบบนี้
- ในวงวิชาการช่วงทศวรรษ 1960 การเขียนโปรแกรมเชิงโครงสร้างได้พัฒนาขึ้นเพื่อทำให้ภาษาเหล่านี้จัดการได้ง่ายกว่าเดิม และผลลัพธ์คือ ALGOL 60 ซึ่งต่อมาสมาชิกส่วนใหญ่ของสายนี้ก็แตกแขนงมาจากที่นี่
- เมื่อเวลาผ่านไป มีแนวโน้มที่จะดูดซับคุณสมบัติจากภาษาแม่แบบดั้งเดิมอื่น
- ในทศวรรษ 1980 แนวคิดจากสาย Self ถูกนำมาผนวกในรูปของคลาสเพื่อใช้เป็นวิธีนิยามชนิดข้อมูลและรองรับพหุสัณฐาน
- หลังปี 2010 แนวคิดจากสาย ML ก็เริ่มปรากฏ
-
Lisp
- เป็นไวยากรณ์ที่ผสาน นิพจน์แบบพรีฟิกซ์ที่ครอบด้วยวงเล็บ เข้ากับการแทนค่าด้วยลิสต์
(+ 2 3)(defun square (x) (* x x))(* (square 3) 3)
- มี การแทนค่าด้วยลิสต์ ที่ล้อมด้วยวงเล็บและคั่นรายการด้วยช่องว่างฝังอยู่ในภาษา ทำให้ตัวโค้ดเองอยู่ในรูปแบบลิสต์
- มาโครสามารถรับลิสต์มาแก้ไข แล้วส่งโค้ดที่แก้ไขแล้วต่อให้คอมไพเลอร์ได้ จึงเปิดทางให้โปรแกรมเมอร์นิยามความหมายของภาษาใหม่ได้
- ในการเขียนโค้ดส่วนใหญ่ มักมีพฤติกรรมคล้ายภาษาแม่แบบดั้งเดิมอื่น โดยมากคือ ALGOL หรือ ML แต่ ระบบมาโคร คือจุดที่ทำให้แตกต่าง
- ไวยากรณ์
loopของ Common Lisp เองก็ไม่ได้เป็นความสามารถที่ฝังมากับภาษา แต่ถูกนิยามเป็นมาโคร - แม้ระยะแรกจะมี Lisp หลายสายย่อย แต่ชุมชนก็ได้ฉันทามติที่ Common Lisp
- Sussman และ Steele สำรวจว่าฟังก์ชันเพียงอย่างเดียวทำอะไรได้แค่ไหน จนสร้าง Scheme ขึ้นมา
- มีการใช้ Lisp สำหรับจุดประสงค์เฉพาะ เช่น Lush สำหรับงานคำนวณเชิงตัวเลข, AutoLISP เป็นภาษาสคริปต์ของ AutoCAD, และ Emacs Lisp สำหรับกำหนดพฤติกรรมของโปรแกรมแก้ไข Emacs
- ในยุคหลัง Clojure ได้ก้าวขึ้นมาเป็นแขนงหลักที่สามของสาย Lisp
- เกิดขึ้นช้ากว่า Fortran ราว 1 ปี และเป็นตระกูลภาษาที่เก่าแก่เป็นอันดับสองซึ่งยังคงใช้งานมาจนถึงปัจจุบัน
- จุดตั้งต้นของมันคือ คำถามทางคณิตศาสตร์ ว่าจะเขียนโครงสร้างทางคณิตศาสตร์ที่สามารถประเมินนิพจน์ของตัวเองได้อย่างไร
- John McCarthy ให้คำตอบในปี 1958 และจากนั้นก็ถูกนำไปทำงานบนคอมพิวเตอร์
- Lisp ยุคแรกไม่เข้ากับเครื่องในเวลานั้นนักเพราะภูมิหลังทางคณิตศาสตร์ ทำให้ประเด็นอย่างหน่วยความจำและรอบ CPU ซึ่งไม่ใช่เรื่องในคณิตศาสตร์กลายเป็นปัญหา และจำเป็นต้องมีเทคนิคอย่าง garbage collection
- ในช่วงปลายทศวรรษ 1970 ถึงต้นทศวรรษ 1980 เคยมีเครื่องที่ถูกออกแบบขึ้นใหม่ทั้งหมดเพื่อรัน Lisp โดยเฉพาะ
- องค์ประกอบหลายอย่างของสภาพแวดล้อมพัฒนาแบบบูรณาการในปัจจุบันถือกำเนิดขึ้นจากเครื่องเหล่านั้น
- ในช่วงเวลาเดียวกัน Lisp เป็นเครื่องมือหลักของงานวิจัยปัญญาประดิษฐ์ และเมื่อกระแส AI ในทศวรรษ 1980 ไม่สร้างผลลัพธ์อย่างที่คาด Lisp ก็ร่วงลงสู่ AI Winter ไปพร้อมกับวงการนั้น
- หลังจากนั้นก็ยังอยู่รอดมาได้ และเมื่อสมรรถนะคอมพิวเตอร์ดีขึ้นพร้อมกับภาษาอื่นรับคุณสมบัติบางส่วนไปใช้ ความยากในการทำอิมพลีเมนต์ก็ลดลง
- เป็นไวยากรณ์ที่ผสาน นิพจน์แบบพรีฟิกซ์ที่ครอบด้วยวงเล็บ เข้ากับการแทนค่าด้วยลิสต์
-
ML
- ฟังก์ชันเป็น ค่าชั้นหนึ่ง และมี ระบบชนิดแบบสาย Hindley-Milner ที่สามารถแสดงฟังก์ชันได้หลากหลายและยูเนียนแบบติดแท็ก
- การทำซ้ำทั้งหมดอยู่ในรูปของการเรียกซ้ำ
sum [] = 0sum (x:xs) = x + sum xs
- ยังใช้วิธีนิยามฟังก์ชันที่ห่อหุ้มรูปแบบการทำซ้ำ แล้วรับฟังก์ชันอื่นมาใช้เพื่อกำหนดพฤติกรรม
map _ [] = []map f (x:xs) = (f x) : (map f xs)
- บางภาษาอย่าง Miranda และ Haskell ใช้การประเมินแบบขี้เกียจเป็นค่าเริ่มต้น
- ภาษาอื่น ๆ ก็ขยายระบบชนิดไปในหลายทิศทาง
- OCaml พยายามผสานแนวคิดจากภาษาแม่แบบดั้งเดิมสาย Self
- Agda และ Idris ใช้ระบบชนิดแบบ dependent types ที่ผสมค่าและชนิดเข้าด้วยกัน
- 1ML ผสานโมดูลกับชนิด
- จาก ML ได้แตกแขนงเป็น CaML, Standard ML, OCaml
- ยังมีสายที่เกี่ยวข้องต่อเนื่องอย่าง Miranda, Haskell, Agda และ Idris
- ML เดิมเป็น meta-language ของโปรแกรมพิสูจน์ทฤษฎีบทที่พัฒนาใน Cambridge ประเทศอังกฤษ และชื่อของมันก็มาจากที่นี่
- ต่อมามันแพร่กระจายออกจากบริบทเดิมจนกลายเป็นภาษาอิสระ โดยได้รับความนิยมในยุโรป โดยเฉพาะในอังกฤษและฝรั่งเศส
-
Self
- โปรแกรมประกอบด้วย ชุดของอ็อบเจ็กต์ ที่ส่งข้อความถึงกัน และการทำงานทั้งหมดก็ถูกสร้างขึ้นด้วยวิธีนี้
- อ็อบเจ็กต์ใหม่ถูกสร้างโดยการส่งข้อความไปยังอ็อบเจ็กต์เดิม
- แม้แต่คำสั่งเงื่อนไขก็ทำผ่านตัวแปรที่อ้างถึงอ็อบเจ็กต์ true หรือ false ตัวใดตัวหนึ่ง
- อ็อบเจ็กต์ทั้งสองรับข้อความที่มีฟังก์ชันสำหรับกรณีจริงและกรณีเท็จเป็นพารามิเตอร์
- อ็อบเจ็กต์ true จะเรียกฟังก์ชันตัวแรก ส่วนอ็อบเจ็กต์ false จะเรียกฟังก์ชันตัวที่สอง
- โค้ดที่เรียกไม่รู้ว่าเป็นอ็อบเจ็กต์ใด รู้เพียงแค่ว่าส่งข้อความออกไป
- ลูปก็ใช้แนวทางเดียวกัน และหากสร้างอ็อบเจ็กต์ที่เหมาะสมแล้ววางไว้ในตำแหน่งที่เหมาะสม ก็สามารถ นิยามความหมายของภาษาทั้งหมดใหม่ ได้
- ภาษาประเภทนี้มักเก็บซอร์สไว้ใน สภาพแวดล้อมแบบสด แทนที่จะเป็นไฟล์ข้อความ
- โปรแกรมเมอร์แก้ไขระบบที่กำลังทำงานอยู่ แล้วบันทึกสถานะนั้น แทนการคอมไพล์ไฟล์เพื่อสร้างระบบ
- ตัวอย่างสำคัญคือ Smalltalk และ Self
- หลายภาษานำเอาวิธีส่งข้อความของตระกูลนี้ไปใช้เพียงบางส่วน และการรับไปใช้บางส่วนเช่นนี้มักถูกเรียกว่า object-oriented programming
- ส่วนใหญ่มีพื้นฐานจาก Smalltalk และมีเพียง JavaScript เท่านั้นที่เป็นข้อยกเว้น เพราะสืบมาจากระบบอ็อบเจ็กต์แบบไร้คลาสของ Self
- ระบบอ็อบเจ็กต์ของ Common Lisp ขยายแนวคิดนี้ให้กว้างขึ้น โดยที่รันไทม์เลือกโค้ดที่จะรันโดยอิงจาก พารามิเตอร์ทั้งหมด ไม่ใช่แค่อ็อบเจ็กต์ตัวรับข้อความเพียงตัวเดียว
- Erlang เปลี่ยนทิศจากการที่กระแสการทำงานย้ายไปมาระหว่างอ็อบเจ็กต์ ไปสู่การที่ เธรดการทำงานแบบขนาน ฟังและส่งข้อความกันอย่างชัดเจน
- ภาษาต้นฉบับคือ Smalltalk ซึ่งพัฒนาขึ้นที่ Xerox Parc ในช่วงปลายทศวรรษ 1970 และทศวรรษ 1980
- ในทศวรรษ 1980 มีระบบ Smalltalk เชิงพาณิชย์หลายตัว และ IBM ก็ใช้ Smalltalk ในการพัฒนาชุดเครื่องมือเขียนโปรแกรม VisualAge สำหรับภาษาอื่น
- ปัจจุบัน Smalltalk ยังคงอยู่เป็นหลักในรูปของโอเพนซอร์ส Pharo Smalltalk
- มีงานวิจัยจำนวนมากเกี่ยวกับการรัน Smalltalk ให้เร็วและมีประสิทธิภาพ และจุดสูงสุดของแนวทางนี้คือ โครงการ Strongtalk
- ความค้นพบจาก Strongtalk มีความสำคัญทางประวัติศาสตร์เพราะกลายเป็นรากฐานของ คอมไพเลอร์ JIT HotSpot ของ Java
- Smalltalk รับแนวคิดเรื่องค่าและชนิดมาจากภาษาก่อนหน้าแล้วใช้สร้างคลาส โดยอ็อบเจ็กต์ทุกตัวมีคลาสที่กำหนดชนิดให้ และคลาสนั้นก็สร้างอ็อบเจ็กต์ของชนิดนั้น
- Self ตัดแนวคิดเรื่องคลาสออก เหลือเพียงอ็อบเจ็กต์เท่านั้น
- ด้วยเหตุที่เป็นรูปแบบที่บริสุทธิ์กว่า จึงเลือก Self เป็นตัวอย่างมาตรฐานของภาษาแม่แบบดั้งเดิมนี้
-
Forth
- ภาษาสแตกมีลักษณะเหมือน ภาพกลับของ Lisp และใช้ไวยากรณ์เดียวกับเครื่องคิดเลขแบบ reverse Polish notation ของ Hewlett Packard
- มันมี data stack และเมื่อเขียนลิเทอรัลอย่าง
42ค่านั้นจะถูก push ลงสแตก ส่วนชื่อฟังก์ชันจะทำงานกับสแตกโดยไม่มีพารามิเตอร์ที่ระบุอย่างชัดเจน - แม้แต่เลขคณิตง่าย ๆ ก็เขียนในรูปกลับด้านอย่าง
2 3 + 5 * - การนิยามฟังก์ชันก็สั้นมากเช่นกัน
- ใน Forth ส่วนใหญ่
:ใช้สำหรับนิยามคำใหม่ squareมีความหมายเทียบเท่ากับการเรียกdupและ*dupคือการคัดลอกค่าบนสุดของสแตก ส่วน*คือการคูณสองค่าบนสุด
- ใน Forth ส่วนใหญ่
- สามารถดักตัว parser แล้วแทนที่ด้วยโค้ดของตัวเองได้ จึง แทนที่ไวยากรณ์ทั้งหมดได้
- เป็นเรื่องปกติที่จะพบโปรแกรม Forth ที่นิยามภาษาย่อย เช่น ชุดย่อยของ Fortran, ผังแพ็กเก็ต, หรือการ parse แผนภาพ ASCII ที่แทนการเปลี่ยนผ่านของ state machine โดยตรง
- รวมถึงสายต่าง ๆ ของ Forth, PostScript, Factor และ Joy
- Joy เป็นภาษาฟังก์ชันล้วนที่ใช้รูปแบบทางคณิตศาสตร์ของการประกอบแทนสแตก
- Forth ถูกเขียนขึ้นครั้งแรกในปี 1970 เพื่อ ควบคุมกล้องโทรทรรศน์วิทยุ
- หลังจากนั้นก็แพร่หลายไปทั่วระบบฝังตัว
- ระบบ Forth บูตสแตรปได้ง่ายมากพอจนมีสายย่อยที่โปรแกรมเมอร์หลายคนสร้างขึ้นตามวัตถุประสงค์ของตัวเองนับสิบแบบ
- PostScript ปรากฏขึ้นในทศวรรษ 1980 เพื่อเป็นวิธีที่ยืดหยุ่นในการอธิบายเอกสารให้เครื่องพิมพ์
- PostScript มีข้อจำกัดมากกว่า Forth ในหลายด้าน แต่ก็นิยามปฏิบัติการพื้นฐานสำหรับการจัดวางกราฟิกไว้ในภาษา
-
APL
- ทุกสิ่งในภาษานี้คือ อาร์เรย์ n มิติ
- ตัวดำเนินการประกอบด้วยสัญลักษณ์หนึ่งหรือสองตัว และทำงานระดับสูงกับอาร์เรย์ทั้งก้อน
- รูปแบบการเขียนมีความอัดแน่นสูงมาก จนสายสัญลักษณ์เองกลายเป็นเครื่องหมายแทนการดำเนินการโดยไม่จำเป็นต้องตั้งชื่ออื่น
- ตัวอย่างเช่น การคำนวณค่าเฉลี่ยของตัวแปร
xเขียนได้เป็น(+⌿÷≢) x - ตัวอย่างสำคัญคือ APL, J, K
- การดำเนินการลำดับสูงกับอาร์เรย์ถูกส่งออกบางส่วนไปยังสภาพแวดล้อมอื่นมากมาย เช่น MATLAB, NumPy และ R
- APL เริ่มต้นจากสัญกรณ์ทางคณิตศาสตร์ที่ Kenneth Iverson สร้างขึ้นในทศวรรษ 1960 ก่อนจะถูกนำมาทำงานบนคอมพิวเตอร์
- หลังจากนั้นก็ยังคงมีฐานผู้สนับสนุนเฉพาะกลุ่มอย่างต่อเนื่องในหมู่ผู้ที่ทำงานคำนวณหนัก
- ภาษาเชื้อสายอย่าง K ได้รับความนิยมมากในแวดวงการเงิน
-
Prolog
- โปรแกรมประกอบด้วยชุดของข้อเท็จจริง
father(bob, ed).father(bob, jane).
- ยังใช้ ข้อเท็จจริงที่ยังไม่ลงค่าตัวแปร เพื่ออนุมานข้อเท็จจริงจากข้อเท็จจริงอื่น
grandfather(X, Y) :- father(X, Z), father(Z, Y).
- รันไทม์ของ Prolog รับข้อเท็จจริงเหล่านี้และคำสืบค้น แล้วทำการค้นหาเพื่อหาผลลัพธ์
- หากเลือกโครงสร้างนิยามข้อเท็จจริงอย่างเหมาะสม ก็จะได้ ความสมบูรณ์ทัวริง
- ใน Prolog พจน์ที่ประกอบกันเป็นข้อเท็จจริงถือเป็นชนิดข้อมูลเฉพาะในตัวเอง ซึ่งสามารถสร้างขึ้นแล้วส่งต่อให้รันไทม์ได้
- ในแง่นี้มันอยู่ในตำแหน่งคล้ายกับมาโครของ Lisp หรือการเปลี่ยน parser ของ Forth
- เนื่องจากโปรแกรม Prolog โดยแก่นแท้คือการค้นหา การปรับแต่งจึงมักเน้นที่ การควบคุมลำดับการค้นหา และการตัดเส้นทางที่ไม่ก่อผลลัพธ์ทิ้งตั้งแต่ต้น คล้ายการสืบค้นฐานข้อมูล
- รวมถึง Prolog, Mercury, Kanren
- การเขียนโปรแกรมจริงในตระกูลภาษาแม่แบบดั้งเดิมนี้ส่วนใหญ่เกิดขึ้นใน Prolog เอง และชุมชนก็มีความเป็นเอกภาพสูงมาก
- นักตรรกศาสตร์ฝรั่งเศสในทศวรรษ 1970 ตระหนักว่าโปรแกรมสามารถแทนได้ด้วย ตรรกะอันดับหนึ่ง จึงเริ่มพยายามทำอิมพลีเมนต์
- ในทศวรรษ 1980 โครงการคอมพิวเตอร์ยุคที่ 5 ของญี่ปุ่นเดิมพันกับ Prolog อย่างมาก แต่เมื่อโครงการล้มเหลว ชื่อเสียงของ Prolog ก็ลดลงตามไปด้วย
- ถึงอย่างนั้น ตลอดหลายสิบปีก็ยังมีงานวิจัยต่อเนื่องทั้งเพื่อทำให้รันไทม์ของ Prolog มีประสิทธิภาพในกรณีส่วนใหญ่ และเพื่อเพิ่มความสามารถใหม่
- เมื่อเพิ่มความสามารถอย่าง ข้อจำกัดเชิงตัวเลข ก็พัฒนาไปสู่การเขียนโปรแกรมเชิงตรรกะแบบมีข้อจำกัด
- Prolog ยังคงปรากฏอยู่ในพื้นที่เฉพาะทาง
- การตรวจชนิดของ Java เคยถูกทำด้วย Prolog อยู่หลายปี
- เครื่องมือค้นหาซอร์สโค้ดยุคแรกของ Facebook ก็มีพื้นฐานบน Prolog
- โปรแกรมประกอบด้วยชุดของข้อเท็จจริง
จะนำไปใช้อย่างไร
- สำหรับโปรแกรมเมอร์ส่วนใหญ่ ภาษาบางส่วนหรือทั้งหมดในกลุ่มนี้อาจดูแปลกแยกมาก แต่ก็ยังคุ้มที่จะลงทุนเวลาเพื่อ เส้นทางความคิด และความเป็นไปได้ใหม่ ๆ ที่แต่ละแบบมอบให้
- สิ่งสองอย่างที่ดูต่างกันอย่างสิ้นเชิงจากมุมมองแบบ ALGOL มักกลายเป็นเพียงความต่างเล็กน้อยเมื่อมองจากอีกมุมหนึ่ง
-
ลำดับความสำคัญ
- โปรแกรมเมอร์ทุกคนควรรู้ ภาษาในสาย ALGOL อย่างน้อยหนึ่งภาษาให้ดี
- หลังจากนั้นแนะนำให้เรียน SQL ซึ่งเป็นภาษาในสาย Prolog
- ในเส้นทางอาชีพ มันให้ประโยชน์มากเป็นอันดับรองจาก ALGOL
-
การขยายต่อจากนั้น
- หลังจากเชี่ยวชาญสองสายข้างต้นแล้ว การเรียนภาษาใหม่ปีละหนึ่งภาษาในสายแม่แบบดั้งเดิมที่ยังไม่คุ้นเคยจะให้ผลดีในระยะยาว
- ภาษาและลำดับที่แนะนำในแต่ละสายมีดังนี้
- Lisp: PLT Racket
- ML: Haskell
- Self: Self
- Prolog: Prolog
- Forth: gForth
- APL: K ใช้งานผ่าน
ok
-
การปรับลำดับ
- หากทำงานคำนวณเชิงตัวเลขมาก ควรเรียน K ให้เร็วขึ้น
- หากทำ embedded programming มาก ควรเรียน gForth ให้เร็วขึ้น
- อย่างไรก็ตาม ลำดับเองหรือการเลือกภาษาที่แน่ชัดไม่ใช่ประเด็นสำคัญ
- จะเรียน Standard ML หรือ OCaml แทน Haskell, Common Lisp แทน PLT Racket, หรือ Factor แทน gForth ก็อยู่ในขอบเขตที่ใช้ได้
-
ข้อมูลเสริมในเชิงอรรถ
- แม้เรียน SQL แล้ว ก็ยังจำเป็นต้องเรียน Prolog เอง อยู่ดี
- เพราะรูปแบบการใช้งานจริงต่างจาก SQL มากพอสมควร
- มีความเห็นจากผู้อ่านว่าหากต้องการเข้าใจ Forth อย่างลึกซึ้ง แนวทางทั่วไปคือสร้างอิมพลีเมนต์ของ Forth ขึ้นเอง
- มีการกล่าวว่า Forth เล็กพอที่คนคนเดียวจะสร้างขึ้นจากศูนย์ได้ในเวลาค่อนข้างสั้น
- gForth เป็นอิมพลีเมนต์ที่เหมาะสำหรับเรียนรู้ ANS Forth
- กล่าวถึง FORTH Fundamentals, Volume 1 ของ McCabe ในฐานะสื่อการเรียนรู้
- และยังกล่าวถึง PygmyForth, eForth, colorForth ให้ลองศึกษาเพิ่มเติมด้วย
- แม้เรียน SQL แล้ว ก็ยังจำเป็นต้องเรียน Prolog เอง อยู่ดี
5 ความคิดเห็น
น่าสนุกดีนะ
ตอนเรียนมหาวิทยาลัย ผมเคยเรียนวิชาเอกและทำการบ้านด้วยภาษาในสาย ALGOL, Lisp และ Prolog พอมาเห็นแล้วก็ทำให้นึกถึงความหลังขึ้นมาเลยครับ
ภาษาเหล่านั้นทิ้งอิทธิพลไว้กับภาษาโปรแกรมกระแสหลักสมัยใหม่มากทีเดียว
แต่ในบรรดานั้น ดูเหมือนมีแค่ Forth ที่อิทธิพลจะน้อยหน่อยนะครับ
ถึงจะพอไม่ต้องถึงขั้นสัญกรณ์นำหน้า แต่ถ้าจะเขียนโค้ดด้วยสัญกรณ์หลังนี่ไม่สะดวกเกินไปจริง ๆ
ความคิดเห็นจาก Hacker News
ตอนเรียนวิชา PL ที่ Tufts เคยได้ลองสร้างภาษาตระกูล imperative, Lisp, ML, Smalltalk แบบมินิด้วยตัวเองอย่างละตัว และก็ดีใจที่ตอนนี้กระบวนการนั้นมีออกมาเป็นตำราเรียนแล้ว เมื่อก่อนยังมีส่วนของ Prolog ด้วย เลยเสียดายที่ตอนนี้หายไป
ถ้าจะขอแก้การจัดหมวดหมู่ในบทความนี้สักอย่าง ผมมองว่า Ruby ไม่ได้เป็นสาย Algol เท่าไร แต่ชัดเจนกว่าในฐานะภาษาเชิงวัตถุ ได้อิทธิพลจาก Smalltalk มาก และแม้แต่ชื่อใน standard library ก็ยังมีร่องรอยนั้นอยู่ เช่นใช้
collectมากกว่าmapอะไรทำนองนั้น ใน Ruby ทุกอย่างเป็นอ็อบเจ็กต์ตั้งแต่ต้นจนจบ และการเรียกเมธอดก็เข้าใจได้อย่างเป็นธรรมชาติกว่าในฐานะการส่งข้อความไปยังอ็อบเจ็กต์ มักถูกเอาไปเทียบกับ Python แต่เส้นทางวิวัฒนาการค่อนข้างต่างกัน และตอนนี้เหมือนจะมาบรรจบกันที่จุดคล้ายกันในเชิง ecosystem สำหรับผม Ruby ให้ความรู้สึกเหมือน อัลปาก้าแสนนุ่มฟู มากกว่า PythonHello Worldแต่แม้แต่ชนิดข้อมูลพื้นฐานก็กลายเป็นอ็อบเจ็กต์ทั้งหมด ถ้าจะอธิบายให้คนที่ไม่ชอบ OOP เห็นภาพ ก็เอาtype(42)กับdir(42)ให้ดูเพื่อเน้นว่าแม้แต่จำนวนเต็มก็เป็นอ็อบเจ็กต์ผมอยากเพิ่มหมวด ภาษาสำหรับแสดงการพิสูจน์ เข้าไปในลำดับวงศ์ภาษาด้วย เป็นสายที่โปรแกรมก็คือบทพิสูจน์ตาม Curry-Howard correspondence โดย Lean เป็นตัวอย่างเด่น จะมองว่าเป็นหมวดย่อยของ functional ก็ได้ แต่เพราะจุดประสงค์หลักคือการตรวจพิสูจน์มากกว่าการรัน เลยรู้สึกว่าควรมีแกนแยกต่างหาก
ช่วงหลังผมกลับไปดูโปรเจ็กต์เปรียบเทียบภาษาอีกครั้ง เป็นเบนช์มาร์กที่ทำ cycle decomposition แบบขนานของ signed permutation จำนวน 3,715,891,200 แบบสำหรับตัวอักษร 10 ตัว สิ่งที่อยากรู้ไม่ใช่ “ภาษาต้นแบบ” แต่คือในบรรดา ภาษายุคปัจจุบัน ของแต่ละพาราไดม์นั้น มีภาษาไหนที่น่าจะเลือกใช้จริงสำหรับงานเขียนโปรแกรมเชิงวิจัย นอกจากประสิทธิภาพแล้วก็ยังดูด้วยว่าขอความช่วยเหลือจาก AI ได้ง่ายไหม และผมเองอ่านโค้ดกับคิดตามได้สบายหรือเปล่า อีกทั้งเพราะมี AI ช่วย เลยได้ลอง optimize แต่ละภาษาอย่างลึกพอสมควรเหมือนไปเที่ยวชม ผลสรุปอยู่ที่นี่ และโดยเฉพาะที่ F# ขึ้นมาอยู่อันดับบนสุดนี่ค่อนข้างน่าประหลาดใจ
ผมเองก็เคยเขียนบทความคล้าย ๆ กันไว้ที่นี่ ผมเห็นด้วยกับ Algol, Lisp, Forth, APL, Prolog แต่สำหรับภาษาฟังก์ชันที่พลิกวงการ ผมใส่ SASL ซึ่งมาก่อน ML เล็กน้อย และในฐานะตัวแทนเชิงวัตถุ ผมเลือก Smalltalk ที่มาก่อน Self นอกจากนี้ยังใส่ Fortran, COBOL, SNOBOL และ Prograph ด้วย เพราะมองว่าแต่ละตัวเปลี่ยนเกมในคนละแบบ
ผมอยากเพิ่ม ตระกูลเชิงความหมาย เข้าไปในการสนทนานี้ด้วย เช่น Verilog, Petri nets, Kahn process networks, dataflow machines, process calculi, reactive, term rewriting, ตระกูล constraint solver/theorem prover, probabilistic programming และยังมีภาษาอย่าง Unison, Darklang, temporal dataflow, DBSP ที่แม้จะไม่เข้ากับ 7 หมวดเดิมพอดี แต่ในทางปฏิบัติก็ใกล้ระดับพร้อมใช้งานจริงแล้ว อาจดูเหมือนเล่นนอกกติกาไปหน่อย แต่ส่วนใหญ่เป็นโมเดลการคำนวณที่ขนานไปกับเครื่องแบบ von Neumann ผมอยากเขียนบทความแนว “ทุกวิธีการคำนวณที่เรารู้จัก นอกเหนือจาก von Neumann” มาสักพักแล้ว
1+1ให้เป็นADD(1,1)ก็จะ parse ได้ด้วยวิธีที่ผมคุ้นเคย แถมตอนนั้นยังดื้อไม่ยอมเรียน regex เลยทำให้โค้ดออกมาพิลึกพอสมควร และยังจำได้ว่ามีเพื่อนร่วมทีมพูดว่า “Andy บอกว่ามันใช้ได้ งั้นอย่าไปแตะมันเลย” ขณะที่อีกทีมหนึ่งใช้ regex ทำงานเดียวกันได้สั้นกว่าโค้ดผมราว 20 เท่าวิชา “Concepts of programming languages” ที่เคยเรียนที่ TU Delft เป็นวิชาที่ผมชอบที่สุดในสาขาคอมพิวเตอร์ เราเรียน C, ฝั่งฟังก์ชันผ่าน Scala, และ JavaScript ในฐานะตัวอย่างของแนวคิด prototype ซึ่งช่วยมากจนอีกหลายปีต่อมาตอนผมไปเรียน Elixir ก็ง่ายขึ้นเยอะ นอกจากนี้ยังมีวิชาที่ให้เขียนเอเจนต์ Unreal Tournament ด้วยภาษา GOAL ซึ่งเป็นภาษาแบบ Prolog-based ด้วย ผมเองอยู่นานมากกว่าจะเห็นภาพว่า Prolog เอาไปใช้ตรงไหนได้บ้าง แต่สุดท้ายก็ได้เอามันไปทำ spellcheck ที่บังคับให้ประโยค Papiamentu แย่ ๆ ที่ LLM สร้างขึ้นถูกแก้ซ้ำไปเรื่อย ๆ
ผมเห็นด้วยกับแนวคิดที่ว่า “ควรเรียนภาษาคนละประเภทกัน” พอได้เรียน OCaml ผมถึงเริ่มรู้สึกว่าฟังก์ชันคือฟังก์ชันทางคณิตศาสตร์จริง ๆ ส่วน Mathematica ก็ฝึกนิสัยให้มอง expression เองเป็นอินพุตได้ ส่วนสัญกรณ์ Polish แบบย้อนกลับของ PostScript ทำให้ผมรู้สึกเหมือนวิธีคิดถูกเดินสายใหม่ไปเลย ไม่ได้กระทบแค่คณิตศาสตร์พื้นฐานเท่านั้น แต่ผมไม่เห็นด้วยกับความคิดที่ว่าเลือก Java, C#, C++, Python หรือ Ruby ตัวไหนก็เหมือนกัน ถ้าเป้าหมายมีแค่เขียน quicksort มันอาจคล้ายกัน แต่สำหรับคนที่อยากสร้างของจริง การเลือกภาษาทำให้เกิดความต่างแบบ คนละโลก ถ้าคุณยื่น Ruby ให้คนที่อยากทำเกม 3D หรือยื่น Java ให้คนที่อยากทำ exploratory data science หรือ deep learning ก่อนเป็นภาษาแรก ก็อาจทำให้เขาหมดไฟได้
อ่านบทความนี้แล้วนึกถึง 7 languages in 7 weeks ของ Bruce Tate ผมเองก็รู้จัก Erlang ครั้งแรกจากหนังสือเล่มนั้น แต่ในเชิงประวัติศาสตร์ ผมรู้สึกว่าการจัด COBOL กับ Fortran ให้อยู่ในสาย Algol ค่อนข้างฝืน ถึงอย่างนั้นมันก็เตือนให้เห็นว่าประวัติศาสตร์เองโดยธรรมชาติก็ต้องมีการสรุปลดทอนอยู่บ้าง
มีประเด็นเกี่ยวข้องจากการถก HN ครั้งก่อนด้วย อ่านการสนทนาก่อนหน้า ประกอบจะช่วยเห็นบริบทมากขึ้น