(Với lời xin lỗi cho một câu trả lời dài đi theo một hướng khác với phạm vi của trang web: thật lòng tôi rất ngạc nhiên khi thấy câu hỏi ở đây ở vị trí đầu tiên.)
TeX được thiết kế để sắp chữ, không phải để lập trình; Vì vậy, nó tốt nhất là kỳ quặc khi được coi là ngôn ngữ lập trình.
- Donald Knuth, Kiểu chữ kỹ thuật số, trang 235
Tôi đã đọc rất nhiều trong vài năm qua về lịch sử ban đầu (khoảng năm 1977) của TeX, và rất nhiều những gì Knuth đã viết. Kết luận của tôi là thời điểm chúng ta nói về về Te TeX (như một ngôn ngữ lập trình) , một cái gì đó đã sai.
Nếu chúng ta nhìn vào các tài liệu thiết kế ban đầu của người dùng, dành cho TeX được viết trước đó (xem TEXDR.AFT
và TEX.ONE
, được xuất bản trong Kiểu chữ kỹ thuật số ), rõ ràng Knuth đang thiết kế một hệ thống chủ yếu để đánh máy Nghệ thuật lập trình máy tính (ông đã nói (ví dụ ở đây ) rằng những người dùng chính mà anh ta có trong đầu là chính anh ta và thư ký của anh ta), với ý tưởng rằng, được sửa đổi phù hợp, nó có thể hữu ích hơn nói chung. Để tiết kiệm việc gõ, đối với những việc người ta phải lặp đi lặp lại (ví dụ: mỗi lần TAOCP cần bao gồm một trích dẫn từ một tác giả, bạn muốn di chuyển theo chiều dọc theo một số tiền nhất định, đặt một dòng nhất định, chọn một phông chữ nhất định, sắp chữ trích dẫn căn lề phải, chọn một phông chữ khác, gõ tên tác giả là), có các macro.
Bạn có thể đoán được phần còn lại. Những gì chúng ta có ở TeX là một trường hợp của Vô tình Turing-Complete, ( hơn nữa ), ngoại trừ việc nó xảy ra ở giữa một cộng đồng (các nhà khoa học máy tính và nhà toán học, và bản thân DEK cũng là người đổ lỗi cho Mitch) (thật không may) quá thông minh để bỏ qua điều này. (Truyền thuyết kể rằng Michael Spivak chưa bao giờ lập trình trước khi anh ta gặp TeX, nhưng anh ta bị cuốn theo nó đến nỗi cuối cùng anh ta đã viết AMS-TeX, tại thời điểm một trong những macro phức tạp nhất tồn tại.) Bởi vì TeX đã được viết để có thể di động trên một số lượng lớn các hệ thống (đó là một vấn đề lớn vào thời điểm đó), luôn có một sự cám dỗ để làm mọi thứ trong TeX. Bên cạnh đó, vì kinh nghiệm viết trình biên dịch của mình, Knuth đã viết TeX giống như một trình biên dịch, và đôi khi mô tả nó như một trình biên dịch, và nếu chương trình hoạt động trên đầu vào của bạn là một trình biên dịch, thì chắc chắn bạn đang lập trình, phải không?
Bạn có thể đọc thêm một chút về cách Knuth không có ý định cho bất kỳ chương trình nào được thực hiện trong TeX và cách anh ấy đưa vào nhiều tính năng lập trình của TeX chỉ sau khi đá và la hét, trong câu trả lời này . Dù ý định của anh ta là gì, như tôi đã nói, mọi người đã bắt đầu tìm ra cách (ab) sử dụng hệ thống macro TeX để thực hiện các chiến công lập trình đáng ngạc nhiên. Knuth thấy điều này hấp dẫn và (ngoài việc thêm một số tính năng vào TeX chính nó) bao gồm một vài trong số những định tại Phụ lục D “thủ đoạn bẩn thỉu” của Các TeXbook, nhưng nó quay ra, mặc dù tên, rằng “chín ra khỏi ví dụ mười trong đó là được sử dụng trong quá trình thực hiện LaTeX.
Hãy để tôi nói một cách khác: LaTeX, hệ thống vĩ mô mà Leslie Lamport đã viết trên TeX, như một ý tưởng , là một ý tưởng tuyệt vời. Tác giả tài liệu theo cách ngữ nghĩa, có cấu trúc, hướng đến con người, chứ không phải theo cách (trang Knuth) của TeX, (hay như Lamport gọi nó, logic hơn là trực quan ) là một cách tuyệt vời. Nhưng việc thực hiện một cái gì đó phức tạp như LaTeX bằng cách sử dụng các macro TeX chứ không phải bằng ngôn ngữ lập trình phù hợp của trực tuyến, theo quan điểm của tôi và ít nhất là nếu nó được thực hiện ngày hôm nay, ở đâu đó giữa một sai lầm lớn và một hành động bừa bãi. Ngay cả Knuth cũng bị sốc khi mọi người không chỉ mở rộng chương trình TeX thay vì làm mọi thứ trong macro TeX.
Ngày nay có nhiều cách tốt hơn để làm lập trình trực tuyến bạn có thể sử dụng một chương trình bên ngoài bằng bất kỳ ngôn ngữ nào có sẵn rộng rãi trên hầu hết các máy tính của mọi người hoặc bạn có thể sử dụng LuaTeX và chương trình trong Lua (và thực hiện công việc tốt hơn bao giờ hết với macro TeX, bởi vì bạn có thể điều khiển các cấu trúc bên trong và thuật toán ở cấp độ phù hợp). Và nếu bạn làm đúng, bạn có thể có các chương trình hoạt động tốt hơn hoặc nhanh hơn các chương trình được triển khai trong macro TeX.
Nhiệm vụ làm cho các chương trình trong TeX nhanh hơn hầu như rất thú vị khi được nhìn thấy dưới ánh sáng này, và gợi nhớ cho tôi về những từ cuối cùng của bài báo mô tả một người khác vô tình Turing hoàn thành chương trình ngôn ngữ của người Hồi giáo: Tom Wildenhain's On On Turing Completeness of MS PowerPoint ( video ) từ năm ngoái:
Trong khi PPTXTM chứng minh khả năng lý thuyết về phát triển PowerPoint, [BR]. Công việc cũng cần được thực hiện trong tối ưu hóa ứng dụng PowerPoint. Có rất nhiều tiềm năng ở đây để khai thác bộ đệm tự động của PowerPoint cho slide tiếp theo, thông qua vị trí trượt cẩn thận có thể được sử dụng để tăng đáng kể hiệu năng của ứng dụng.
Các giai thoại rằng Lipton mô tả là minh họa. Không chỉ chưa từng tồn tại một ngữ nghĩa chính thức của TeX, mà còn không có khả năng là một. Nó chỉ là quá kỳ quặc, một ngôn ngữ của người Viking về điều đó, và (như tôi hy vọng tôi đã giải thích ở trên) nó thậm chí không có ý định như một ngôn ngữ. Ví dụ, bạn có thể nghĩ rằng bạn đang viết macro dưới dạng hàm, nhưng giới thiệu một ký tự đi lạc duy nhất (thậm chí là khoảng trắng ) trong đó và TeX ngay lập tức coi nó như một hướng dẫn sắp chữ.
Nói tóm lại: TeX quay trở lại việc sắp chữ trong cơ hội sớm nhất và khi nó mở rộng các macro, nó rất miễn cưỡng (thiếu kiên nhẫn để thực hiện công việc sắp chữ của trò chơi Real), và bản mở rộng này có thể phụ thuộc vào hàng trăm loại trạng thái của nó chương trình TeX (các giá trị của các tham số như \hsize
hoặc \baselineskip
, nội dung của các hộp và các thanh ghi khác), đó là lý do tại sao mọi ngữ nghĩa chính thức của TeX phải nhất thiết phải tính đến toàn bộ trạng thái của chương trình và tất cả bộ nhớ của nó, cho đến khi chúng ta kết thúc với một cái gì đó giống như ý nghĩa của mã TeX là bất cứ điều gì TeX thực hiện, trong một hình thức phức tạp hơn chính chương trình TeX.
Rất tốt, (nếu tôi đã thuyết phục bạn) TeX không có ý định làm ngôn ngữ lập trình và không hoạt động như ngôn ngữ thực, không có ngữ nghĩa chính thức và có nhiều cách tốt hơn để lập trình ngày hôm nay - nhưng tất cả điều này không giúp ích gì cho bạn thực tế câu hỏi / vấn đề, mà là trong thực tế, nhiều văn bản có nghĩa là cho chế biến bởi TeX làm sử dụng phức tạp macro (như LaTeX và TikZ), dinh thự tuyệt đẹp của sự phức tạp khổng lồ được xây dựng trên đầu trang của mỗi khác. Làm thế nào chúng ta có thể làm cho nó nhanh hơn và nghĩ ra tối ưu hóa vượt qua vượt qua?
Bạn sẽ không đạt được điều đó với ngữ nghĩa chính thức IMO. Gần đây tôi đã nghĩ về điều này, và sau đây là một số suy nghĩ sơ bộ.
Ấn tượng của tôi là Knuth là một trong những người viết trình biên dịch có kinh nghiệm trong những năm 1960 (đó là lý do tại sao anh ta được yêu cầu viết cuốn sách biên dịch chuyển thành Nghệ thuật lập trình máy tính ), và TeX (theo nhiều cách) đã viết theo cách trình biên dịch được viết vào những năm 1970, nói. Các kỹ thuật và thiết kế trình biên dịch đã được cải thiện kể từ đó, và chương trình TeX cũng vậy. Dưới đây là một số điều có thể được thực hiện, bằng cách tăng tốc mọi thứ:
Về cơ bản, TeX được viết giống như một thói quen diễn giải của người Hồi giáo, trong đó các mắt TeX và mắt miệng (các thói quen đầu vào của nó) cung cấp các hướng dẫn cho bụng dạ của mình (thói quen ngữ nghĩa của nó), được thực hiện từng cái một. (Bạn có thể xem danh sách trong phần 15 của chương trình TeX .) Ví dụ: khi gặp mắt / miệng của TeX \hfill
hoặc \hskip
trong đầu vào của nó, dạ dày nhận được lệnh của hskip, mà nó hoạt động. Điều này tương tự với những gì được gọi là trình thông dịch mã byte ngày nay và có thể có giá trị trong việc tái cấu trúc chương trình TeX để phát ra các mã byte / opcodes này một cách rõ ràng, do đó chúng ta có thể sử dụng các kỹ thuật biên dịch hiện có (thông thường hơn ngày nay). Hoặc ít nhất là lưu trữ chúng để tránh làm lại công việc. Tất nhiên có nhiều thách thức:
Việc thực thi một lệnh trong bụng dạ dày thường vẫn liên quan đến việc đọc đầu vào, tức là công việc của các thói quen đầu vào và các thói quen ngữ nghĩa không xảy ra trong các giai đoạn riêng biệt. Ví dụ, lệnh của hskip, nếu được đưa ra \hskip
(chứ không phải nói \hfill
) sẽ gọi scan_glue
để đọc một đặc tả keo từ đầu vào, do đó có thể liên quan đến việc mở rộng các macro và cứ thế cho đến khi tìm thấy đủ mã thông báo cho keo, để lại ngăn xếp đầu vào trong thực chất nhà nước khác nhau.
Các công cụ như eTeX và pdfTeX và XeTeX và LuaTeX giới thiệu các lệnh và nguyên thủy mới (nguyên thủy eTeX / pdfTex được sử dụng thực tế bởi mọi người trong thực tế); bạn cũng sẽ cần hỗ trợ họ, không chỉ những người trong chương trình TeX ban đầu của Knuth.
Chúng ta có thể làm một cái gì đó giống như thực thi đầu cơ theo kiểu đầu lâu bỏ công việc đó (và làm lại nó) nếu sau đó chúng ta phát hiện ra rằng một đoạn trước đó kết thúc thay đổi một số trạng thái đó. Hiện tại TeX chạy hoàn toàn tuần tự trên 1 bộ xử lý; phần cứng điển hình đã di chuyển theo một hướng khác và nhiều lõi có sẵn.
Thậm chí đơn giản hơn, chúng ta có thể đơn giản lưu trữ công việc (trạng thái TeX đã được truy cập và sửa đổi) bằng một phần nhất định của tệp đầu vào. (Chúng ta có thể thực hiện việc lưu bộ đệm này ở cấp độ đầu vào, kết quả thực của việc mở rộng tất cả các macro, hoặc ở cấp độ của bộ hộp được lắp ráp hoặc tất cả các trạng thái của toàn bộ chương trình.) Ví dụ: nội dung bên trong a \begin{tikzpicture} … \end{tikzpicture}
không thể phụ thuộc nhiều vào trạng thái TeX như bộ đếm số trang, vì vậy khi chúng tôi biên dịch lại tài liệu TeX, chúng tôi chỉ có thể sử dụng lại tất cả công việc - nếu chúng tôi đã theo dõi đủ thông tin để biết rằng nó an toàn để làm như vậy. (Tất nhiên TikZ nói riêng có cách để đưa ra điều này và bao gồm các kết quả, nhưng ý tưởng thì tổng quát hơn.)
Chúng ta có thể sử dụng các kỹ thuật (ví dụ: các kỹ thuật được sử dụng trong lập trình chức năng) để thực hiện một số xử lý TeX với các lỗ Lỗ - ví dụ ngay bây giờ, khi bạn viết \ref{foo}
bằng LaTeX để chỉ số phần (nói trong tương lai), nó chỉ hoạt động trong hai lần biên dịch: đầu tiên toàn bộ tài liệu được xử lý (tất cả các kiểu đoạn văn, nổi được định vị trên các trang, v.v.) với các số phần được ghi ra một tệp phụ trợ, sau đó trên một giây vượt qua tất cảcông việc được thực hiện lại, với số phần thực sự có sẵn lần này. (Loại hack này có thể là không thể tránh khỏi vào thời điểm đó và tôi biết tác động đến thời gian hoạt động là chỉ là một yếu tố không đổi, nhưng thay vào đó, nếu chúng ta có thể xử lý tài liệu bằng một lỗ Lỗ ( một hộp có nội dung không xác định nhưng chiều rộng ước tính) còn lại cho số phần, sau đó ở phần cuối của quá trình xử lý tài liệu có điền vào hộp không? (Có, chiều rộng ước tính của chúng tôi có thể sai và đoạn văn có thể cần xử lý lại và do đó, ngay cả trang, nhưng chúng tôi có thể thực hiện công việc nếu cần hoặc chấp nhận, đối với tốc độ, chế độ trong đó chúng tôi sẽ cho phép độ rộng sai cho số phần.)
Các kỹ thuật tương tự có thể hoạt động để chỉnh sửa tương tác một tài liệu TeX: khi bạn chỉnh sửa một đoạn văn bản, nó có thể được xử lý trực tiếp, với các đoạn trong tương lai chỉ đơn giản là di chuyển xuống galley (giả sử). Chúng tôi biết điều đó là có thể, vì đã có các triển khai TeX (thương mại) thực hiện điều này, ví dụ BaKoMaTeX và Texpad và các Kết cấu trước đây . (Xem video trên trang chủ của BaKoMa-TeX và tương tự TeXpad, ví dụ: video này - Tôi đã thử cái thứ hai và mặc dù nó không có lỗi trong thực tế.)
Không được đánh giá thấp: giá trị của việc hiển thị mọi thứ cho người dùng, làm cho TeX dễ bị gỡ lỗi hơn. Ngay bây giờ, người dùng chỉ nhìn thấy đầu vào TeX của họ và không biết chính xác TeX đang làm gì, ví dụ như họ dành bao nhiêu thời gian cho việc ngắt dòng cho các đoạn văn, hoặc mở rộng macro (và macro nào), nó lắp ráp những hộp nào và vứt đi, những gì đặc biệt đang được viết ra bởi gói nào, v.v. Tôi (có lẽ lạc quan) tin rằng có những người dùng tồn tại muốn xem thông tin này và sẽ thấy nó hữu ích, ví dụ như để biết liệu gói kỳ lạ họ đang sử dụng để che bóng phương trình với độ dốc trong nền có rẻ (thêm ít vào thời gian xử lý) hay không. Bằng cách xem nơi mà rất nhiều công việc lãng phí đang được thực hiện, họ có thể vứt bỏ một số công việc đó (ít nhất là cho đến khi bản in cuối cùng của họ chạy). (Điều này hơi giống như trình biên dịch hoặc các công cụ khác chèn thông tin định hình vào các chương trình.) Làm cho TeX minh bạch hơn và có thể gỡ lỗi có thể là một cải tiến khả năng sử dụng rất lớn, chẳng hạn. (TeX đã khá thân thiện với người dùng và có thể gỡ lỗi cho IMO nếu chúng ta sử dụng TeX đơn giản với rất ít macro, nhưng không phải với LaTeX hoặc cách mà hàng loạt người dùng gặp phải ngày hôm nay.)
Ngoài ra, bất kỳ công việc nào trong tương lai có lẽ nên tính đến (xây dựng) LuaTeX, đây là bản sửa đổi tốt nhất của TeX chúng tôi hiện có.
Tất cả những điều này chỉ là những suy nghĩ vu vơ (tôi đã không thực hiện bất kỳ ý tưởng nào trong số chúng, để biết nỗ lực cần thiết hoặc chúng ta sẽ tăng tốc bao nhiêu), nhưng tôi hy vọng điều này sẽ đi theo hướng nào đó để trả lời câu hỏi của bạn hoặc đưa ra ý tưởng cho bạn trong tương lai .