(ด้วยคำขอโทษสำหรับคำตอบยาว ๆ ที่ไปในทิศทางที่แตกต่างจากขอบเขตของไซต์: ตรงไปตรงมาฉันประหลาดใจที่เห็นคำถามที่นี่ในตอนแรก….)
TeX ถูกออกแบบมาสำหรับการเรียงพิมพ์ไม่ใช่สำหรับการเขียนโปรแกรม ดังนั้นจึงเป็นสิ่งที่ดีที่สุด“ แปลก” เมื่อพิจารณาเป็นภาษาการเขียนโปรแกรม
- Donald Knuth, ตัวอักษรดิจิทัล,หน้า 235
ฉันอ่านมากในช่วงสองสามปีที่ผ่านมาเกี่ยวกับประวัติต้น (ประมาณปี 1977) ของ TeX และสิ่งที่ Knuth เขียนไว้มากมาย ข้อสรุปของฉันคือช่วงเวลาที่เราพูดถึง"TeX (เป็นภาษาโปรแกรม)"มีบางอย่างผิดปกติไปแล้ว
ถ้าเราดูที่“ เอกสารการออกแบบ” ในช่วงต้นสำหรับ TeX ที่เขียนก่อนหน้านี้ (ดูTEXDR.AFT
และTEX.ONE
ตีพิมพ์ในDigital Typography ) เห็นได้ชัดว่า Knuth กำลังออกแบบระบบสำหรับการเรียงพิมพ์The Art of Computer Programming (เขาได้กล่าวไว้ที่นี่ ) ว่าผู้ใช้หลักที่เขามีอยู่ในใจคือตัวเขาเองและเลขานุการของเขา) ด้วยความคิดที่ว่าการแก้ไขอย่างเหมาะสมมันอาจมีประโยชน์มากกว่าปกติ หากต้องการบันทึกการพิมพ์สำหรับสิ่งที่ต้องทำซ้ำ ๆ (เช่นทุกครั้งที่ TAOCP จำเป็นต้องรวมใบเสนอราคาจากผู้เขียนคุณต้องการย้ายในแนวตั้งด้วยจำนวนเงินที่กำหนดตั้งค่ารายการที่แน่นอนรับแบบอักษรบางประเภท อ้างชิดขวาหยิบตัวอักษรอื่นพิมพ์ชื่อผู้แต่ง…) มีมาโคร
คุณสามารถเดาส่วนที่เหลือ สิ่งที่เรามีใน TeX คือกรณีของ"การทำให้ทัวริงสมบูรณ์" ( เพิ่มเติม ) ยกเว้นว่ามันเกิดขึ้นท่ามกลางชุมชน (นักวิทยาศาสตร์คอมพิวเตอร์และนักคณิตศาสตร์และ DEK เองก็คือ "โทษ" ด้วย) ซึ่งเป็นโชคไม่ดี ฉลาดเกินกว่าที่จะเพิกเฉยต่อสิ่งนี้ (มีตำนานกล่าวไว้ว่าMichael Spivakไม่เคยตั้งโปรแกรมก่อนที่เขาจะพบ TeX แต่เขาก็ถูกนำไปด้วยดังนั้นเขาจึงลงเอยด้วยการเขียน AMS-TeX ซึ่งเป็นหนึ่งในแมโครที่ซับซ้อนที่สุดในชีวิต) เนื่องจาก TeX เขียนขึ้น การพกพาข้ามระบบจำนวนมาก (ซึ่งเป็นเรื่องใหญ่ในเวลานั้น) มีความอยากทำทุกอย่างใน TeX เสมอ นอกจากนี้เนื่องจากประสบการณ์การเขียนคอมไพเลอร์ของเขาKnuth เขียน TeX เหมือนคอมไพเลอร์และบางครั้งก็อธิบายเป็นหนึ่งและถ้าโปรแกรมที่ทำงานกับอินพุตของคุณเป็น“ คอมไพเลอร์” แน่นอนว่าคุณกำลังเขียนโปรแกรมใช่ไหม?
คุณสามารถอ่านเพิ่มเติมเกี่ยวกับวิธีที่ Knuth ไม่ต้องการให้มีการเขียนโปรแกรมใน TeX และวิธีที่เขา“ ใส่ในคุณสมบัติการเขียนโปรแกรมของ TeX มากมายหลังจากเตะและส่งเสียงกรี๊ด” ในคำตอบนี้ สิ่งที่เขาตั้งใจก็คืออย่างที่ฉันพูดผู้คนเริ่มคิดหาวิธีการ (ab) ใช้ระบบมาโครของ TeX เพื่อทำให้การเขียนโปรแกรมสำเร็จ นูพบนี้น่าสนใจและ (นอกเหนือจากการเพิ่มคุณสมบัติบางอย่างในเท็กซ์เอง) รวมถึงบางส่วนของเหล่านี้ในภาคผนวก D“เคล็ดลับสกปรก” ของTeXbook,แต่มันกลับกลายเป็นแม้จะมีชื่อที่ว่า “เก้าออกจากตัวอย่างสิบนั้นมี ใช้ในการดำเนินงานของ LaTeX”
ให้ฉันพูดอีกอย่างคือ: LaTeX ระบบมาโครที่ Leslie Lamport เขียนไว้ด้านบนของ TeX เป็นแนวคิดที่ยอดเยี่ยม การเขียนเอกสารในเชิงความหมายโครงสร้างมุ่งเน้นที่มนุษย์มากกว่า (Knuth) วิธีที่เน้นการเพจของ TeX (หรือ Lamport เรียกมันว่าตรรกะมากกว่าภาพ ) เป็นสิ่งที่ยอดเยี่ยม แต่การใช้บางสิ่งที่ซับซ้อนเท่า LaTeX โดยใช้มาโคร TeX มากกว่าในภาษาการเขียนโปรแกรม“ เหมาะสม” คือในมุมมองของฉันและอย่างน้อยถ้ามันเสร็จสิ้นในวันนี้อยู่ระหว่างความผิดพลาดครั้งใหญ่กับการกระทำที่ชั่วร้าย แม้แต่ Knuth ก็ตกใจที่ผู้คนไม่เพียงแค่ขยายโปรแกรม TeX แทนที่จะทำทุกอย่างในแมโคร TeX
วันนี้มีวิธีที่ดีกว่าในการทำ "โปรแกรม"; คุณสามารถใช้โปรแกรมภายนอกในหลายภาษาที่มีอยู่ในคอมพิวเตอร์ของคนส่วนใหญ่หรือคุณสามารถใช้ LuaTeX และโปรแกรมใน Lua (และทำงานได้ดีกว่าที่คุณเคยทำได้ด้วยมาโคร TeX เพียงอย่างเดียวเพราะคุณสามารถควบคุมโครงสร้างภายในและ อัลกอริทึมในระดับที่เหมาะสม) และถ้าคุณทำถูกต้องคุณสามารถมีโปรแกรมที่ทำงานได้ดีกว่าหรือเร็วกว่าโปรแกรมที่ใช้ในมาโคร TeX
งานในการทำโปรแกรมในเท็กซ์ได้เร็วขึ้นเกือบจะน่าขบขันเมื่อมองในแง่นี้และชวนให้นึกถึงฉันของคำพูดสุดท้ายของกระดาษอธิบายอีก“บังเอิญทัวริงสมบูรณ์” โปรแกรม“ภาษา”: ทอม Wildenhain น่ารัก“ ในทัวริงสมบูรณ์ของ MS PowerPoint ( วิดีโอ ) จากปีที่แล้ว:
ในขณะที่ PPTXTM พิสูจน์ความเป็นไปได้ทางทฤษฎีของการพัฒนา PowerPoint, […] งานต้องทำในการเพิ่มประสิทธิภาพแอปพลิเคชัน PowerPoint ด้วย มีความเป็นไปได้มากมายที่นี่ในการใช้ประโยชน์จากการบัฟเฟอร์อัตโนมัติของ PowerPoint ในสไลด์ถัดไปซึ่งอาจใช้การวางสไลด์อย่างระมัดระวังเพื่อเพิ่มประสิทธิภาพของแอปพลิเคชันอย่างมาก
เล็ก ๆ น้อย ๆ ที่อธิบายลิปตันเป็นตัวอย่าง ไม่เพียง แต่ไม่เคยมีความหมายอย่างเป็นทางการของ TeX แต่ก็ไม่น่าจะเป็นเช่นนั้น มันก็แค่ "แปลก" เป็น "ภาษา" สำหรับเรื่องนั้นและ (อย่างที่ฉันหวังว่าฉันได้อธิบายไว้ข้างต้น) มันไม่ได้มีจุดมุ่งหมายเหมือนภาษา ตัวอย่างเช่นคุณอาจคิดว่าคุณกำลังเขียนแมโครเป็นฟังก์ชัน แต่แนะนำอักขระจรจัดตัวเดียว (แม้แต่ช่องว่าง ) ในนั้นและ TeX จะถือว่าเป็นคำสั่งการเรียงพิมพ์ทันที
กล่าวโดยย่อ: TeX เปลี่ยนกลับไปเป็นการเรียงพิมพ์โดยเร็วที่สุดและเมื่อมันขยายมาโครมันก็ทำไม่ดีอย่างใจร้อน (ใจร้อนที่จะได้งานเรียงพิมพ์) "ที่แท้จริง" และการขยายเหล่านี้ขึ้นอยู่กับ "รัฐ" หลายร้อยชนิดภายใน โปรแกรม TeX (ค่าพารามิเตอร์เช่น\hsize
หรือ\baselineskip
เนื้อหาของกล่องและรีจิสเตอร์อื่น ๆ ... ) ซึ่งเป็นเหตุผลที่ความหมายทางการของ TeX ต้องเป็นสิ่งที่คำนึงถึงสถานะทั้งหมดของโปรแกรมและหน่วยความจำทั้งหมดจนกระทั่งเรา ท้ายเรื่อง“ ความหมายของรหัส TeX คือสิ่งที่ TeX ทำ” ในรูปแบบที่ซับซ้อนกว่าโปรแกรม TeX
ดีมาก (ถ้าฉันเชื่อมั่นคุณ) TeX ไม่ได้ตั้งใจเป็นภาษาการเขียนโปรแกรมและไม่ทำงานเหมือนจริงไม่มีความหมายอย่างเป็นทางการและมีวิธีที่ดีกว่าในการเขียนโปรแกรมวันนี้ - แต่ทั้งหมดนี้ไม่ได้ช่วยคุณ ที่เกิดขึ้นจริงคำถาม / ปัญหาซึ่งก็คือว่าในทางปฏิบัติเอกสารจำนวนมากมีความหมายสำหรับการประมวลผลโดยเท็กซ์ทำใช้แมโครซับซ้อน (เช่นน้ำยางข้นและ TikZ) edifices สวยงามของความซับซ้อนมหึมาขึ้นด้านบนของแต่ละอื่น ๆ เราจะทำให้เร็วขึ้นและคิด“ การเพิ่มประสิทธิภาพผ่าน” ได้อย่างไร
คุณจะไม่ได้รับความหมายอย่างเป็นทางการที่ IMO ฉันเพิ่งคิดเกี่ยวกับเรื่องนี้และต่อไปนี้เป็นความคิดเบื้องต้น
ความประทับใจของฉันคือ Knuth เป็นหนึ่งในนักเขียนคอมไพเลอร์ที่มีประสบการณ์ในปี 1960 (นั่นคือสาเหตุที่เขาถูกขอให้เขียนหนังสือคอมไพเลอร์ที่กลายเป็นศิลปะแห่งการเขียนโปรแกรมคอมพิวเตอร์ ) และ TeX (ในหลาย ๆ วิธี) เขียนในปี 1970 พูด เทคนิคและการออกแบบคอมไพเลอร์ได้รับการปรับปรุงตั้งแต่นั้นมาและโปรแกรม TeX ก็สามารถทำได้ นี่คือบางสิ่งที่สามารถทำได้โดยการเร่งสิ่งต่าง ๆ :
หัวใจสำคัญ TeX ถูกเขียนเหมือน "รูทีนการตีความ" ที่ "ดวงตา" และ "ปาก" ของ TeX (รูทีนอินพุต) ส่งคำสั่งไปยัง "กระเพาะอาหาร" (รูทีนความหมาย) เพื่อดำเนินการทีละอย่าง (คุณสามารถดูรายการในส่วนที่ 15 ของโปรแกรม TeX ) ตัวอย่างเช่นเมื่อพบตา / ปากของ TeX \hfill
หรือ\hskip
ในการป้อนข้อมูลกระเพาะอาหารจะได้รับคำสั่ง "hskip" ซึ่งจะทำงาน สิ่งนี้คล้ายกับสิ่งที่เรียกว่า bytecode ล่ามวันนี้และอาจมีค่าในการ refactoring โปรแกรม TeX เพื่อปล่อย bytecodes / opcode เหล่านี้อย่างชัดเจนเพื่อให้เราสามารถใช้เทคนิคคอมไพเลอร์ที่มีอยู่ หรืออย่างน้อยก็แคชพวกเขาเพื่อหลีกเลี่ยงการทำซ้ำงาน แน่นอนว่ามีความท้าทายมากมาย:
การดำเนินการของคำสั่งใน "กระเพาะอาหาร" มักจะเกี่ยวข้องกับการอ่านอินพุตเช่นงานของอินพุตรูทีนและรูทีนเชิงความหมายจะไม่เกิดขึ้นในเฟสที่แยกกัน เช่นคำสั่ง "hskip" หากได้รับ\hskip
(แทนที่จะพูด\hfill
) จะเรียกscan_glue
ให้อ่านข้อมูลจำเพาะของกาวจากอินพุตซึ่งจะสามารถเกี่ยวข้องกับการขยายมาโครและอื่น ๆ จนกว่าจะพบโทเค็นเพียงพอสำหรับกาวออกจากสแต็กอินพุต รัฐที่แตกต่างกันอย่างมีนัยสำคัญ
เอ็นจิ้นเช่น eTeX และ pdfTeX และ XeTeX และ LuaTeX แนะนำคำสั่งใหม่และคำสั่งพื้นฐาน (eTeX / pdfTex แบบดั้งเดิมถูกใช้จริงโดยทุกคนในทางปฏิบัติ); คุณจะต้องสนับสนุนพวกเขาด้วยไม่ใช่เฉพาะในโปรแกรม TeX ดั้งเดิมของ Knuth
เราสามารถทำบางสิ่งเช่น "การประมวลผลเก็งกำไร" ประมวลผลย่อหน้าในอนาคต (อาจเริ่มจากจุดตรวจสอบตามธรรมชาติเช่นส่วนใหม่หรือบท) ในแบบคู่ขนาน (ใช้หลายแกนกลาง) ติดตามสถานะ TeX ภายในทั้งหมดที่พวกเขาใช้ (ขึ้นอยู่กับ) ออกไปทำงานนั้น (และทำซ้ำ) ถ้าในภายหลังเราพบว่าย่อหน้าก่อนหน้านี้จบลงด้วยการเปลี่ยนสถานะบางอย่าง ในขณะนี้ TeX ทำงานตามลำดับทั้งหมดบนโปรเซสเซอร์ 1 ตัว ฮาร์ดแวร์ทั่วไปได้ย้ายไปในทิศทางที่แตกต่างกันและมีหลายคอร์ให้ใช้งาน
แม้จะง่ายกว่านี้เราสามารถแคชงาน (สถานะของ TeX ที่เข้าถึงและแก้ไขได้) โดยบางส่วนของไฟล์อินพุต (เราสามารถทำการแคชนี้ที่ระดับอินพุต - ผลลัพธ์สุทธิของการขยายมาโครทั้งหมด - หรือที่ระดับของชุดกล่องที่ประกอบกันหรือไปจนถึงสถานะทั้งหมดของโปรแกรม) เช่นเนื้อหาภายใน a \begin{tikzpicture} … \end{tikzpicture}
ไม่น่าจะขึ้นอยู่กับสถานะ TeX มากเช่นตัวนับหมายเลขหน้าดังนั้นเมื่อเราทำการคอมไพล์เอกสาร TeX ใหม่เราสามารถนำงานทั้งหมดกลับมาใช้ใหม่ - ถ้าเราติดตามข้อมูลเพียงพอที่จะรู้ว่ามันปลอดภัยที่จะทำเช่นนั้น (โดยเฉพาะอย่างยิ่ง TikZ มีวิธีที่จะทำให้สิ่งนี้เป็นรูปเป็นร่างและรวมถึงผลลัพธ์ แต่ความคิดนั้นกว้างกว่า)
เราสามารถใช้เทคนิค (เช่นที่ใช้ในการเขียนโปรแกรมการทำงาน) เพื่อทำการประมวลผล TeX บางอย่างด้วย "หลุม" - เช่นตอนนี้เมื่อคุณเขียน\ref{foo}
ใน LaTeX เพื่ออ้างถึงหมายเลขส่วน (พูดในอนาคต) มันทำงานได้ในการรวบรวมสองครั้งเท่านั้น: ก่อนเอกสารทั้งหมดจะถูกประมวลผล (เรียงพิมพ์ย่อหน้าทั้งหมดลอยอยู่ในตำแหน่งบนหน้า ฯลฯ ) ด้วยหมายเลขส่วนที่ถูกเขียนออกไปยังไฟล์เสริมจากนั้นเป็นครั้งที่สองผ่านทั้งหมดงานจะทำอีกครั้งด้วยหมายเลขส่วนที่สามารถใช้ได้จริงในเวลานี้ (แฮ็คชนิดนี้อาจหลีกเลี่ยงไม่ได้ในเวลานั้นและฉันรู้ว่าผลกระทบต่อเวลาทำงานคือ“ เพียงปัจจัยคงที่” แต่…..) แต่ถ้าเราสามารถประมวลผลเอกสารด้วย“ รู” (แทน) ได้ กล่องที่มีเนื้อหาที่บึกบึน แต่มีความกว้างโดยประมาณ) เหลือสำหรับหมายเลขส่วนจากนั้นเมื่อสิ้นสุดการประมวลผลเอกสารจะเติมข้อมูลในกล่อง (ใช่ความกว้างโดยประมาณของเราอาจผิดไปและย่อหน้าอาจต้องทำการประมวลผลซ้ำและแม้กระทั่งหน้ากระดาษ แต่เราสามารถทำงานได้หากจำเป็นหรือยอมรับความเร็วโหมดที่เราจะอนุญาตให้ใช้ความกว้างที่ไม่ถูกต้องสำหรับ หมายเลขส่วน)
เทคนิคที่คล้ายกันสามารถใช้แก้ไขเอกสาร TeX แบบโต้ตอบได้: เมื่อคุณแก้ไขย่อหน้ามันสามารถประมวลผล“ สด” ได้โดยที่ย่อหน้าในอนาคตเพียงเลื่อนไปที่ห้องครัว (พูด) เรารู้ว่ามันเป็นไปได้ที่มีอยู่แล้ว (พาณิชย์) การใช้งานเท็กซ์ที่ทำเช่นนี้เช่น BaKoMaTeX และ Texpad และอดีตพื้นผิว (ดูวิดีโอในหน้าแรกของBaKoMa-TeXและในทำนองเดียวกันกับ TeXpad ของเช่นวิดีโอนี้ - ฉันลองหลังและมันแทบไม่น่าเชื่อเลยในทางปฏิบัติ)
ไม่ควรมองข้าม: ค่าของการแสดงสิ่งต่าง ๆ ให้กับผู้ใช้ทำให้ TeX สามารถ debuggable ได้มากขึ้น ตอนนี้ผู้ใช้เห็นเฉพาะอินพุต TeX ของพวกเขาและไม่มีความคิดอย่างชัดเจนว่าสิ่งใดที่ TeX ทำงานเช่นเวลาที่ใช้ในการแบ่งบรรทัดสำหรับย่อหน้าหรือในการขยายแมโคร (และมาโครตัวใด) กล่องที่ประกอบและ ทิ้งสิ่งที่เขียนเป็นพิเศษซึ่งบรรจุภัณฑ์ ฯลฯ ฉัน (อาจมองโลกในแง่ดี) เชื่อว่ามีผู้ใช้ที่ต้องการดูข้อมูลนี้และจะพบว่ามีประโยชน์เช่นรู้ว่าพวกเขาใช้ห่อแปลก ๆ หรือไม่ สมการที่มีการไล่ระดับสีในพื้นหลังนั้นมีราคาถูก (เพิ่มเพียงเล็กน้อยกับเวลาประมวลผล) หรือไม่ โดยการดูว่ามีงานที่สิ้นเปลืองจำนวนมากพวกเขาสามารถโยนงานบางส่วนออกไป (อย่างน้อยก็จนกว่าจะพิมพ์ครั้งสุดท้าย) (ซึ่งคล้ายกับคอมไพเลอร์หรือเครื่องมืออื่น ๆ ที่แทรกข้อมูลการทำโปรไฟล์ลงในโปรแกรม) การทำให้ TeX มีความโปร่งใสและ debuggable มากขึ้นอาจเป็นการปรับปรุงการใช้งานที่มากเช่น (TeX นั้นค่อนข้างใช้งานง่ายและสามารถ debuggable ได้ในขณะนี้ IMO ถ้าเราใช้เท็กซ์ธรรมดาส่วนใหญ่ที่มีมาโครน้อยมาก แต่ไม่ใช่กับ LaTeX หรือผู้ใช้พบเจอกันจำนวนมากในวันนี้)
นอกจากนี้งานในอนาคตควรคำนึงถึง (build on) LuaTeX ซึ่งเป็นการปรับเปลี่ยนที่ดีที่สุดของ TeX ที่เรามีอยู่ในปัจจุบัน
ทั้งหมดเหล่านี้เป็นเพียงความคิดที่ไม่ได้ใช้งาน (ฉันไม่ได้ดำเนินการใด ๆ เพื่อรับรู้ถึงความพยายามที่จำเป็นหรือการเร่งความเร็วที่เราจะได้รับ) แต่ฉันหวังว่าสิ่งนี้จะช่วยตอบคำถามของคุณหรือให้แนวทางในอนาคต .