
我最近發布了一個關於用 plain TeX 編寫巨集來修改使用者指定清單中的元素的問題。我隨口提到我不喜歡 TeX 的介面,所以有人把我轉向 LaTeX3,正如手冊所承諾的那樣,它應該更像是一種現代程式語言。我剛開始使用 TeX 編程,所以試圖理解手冊是一場艱苦的戰鬥。我認為這是因為手冊是為有經驗的 TeX 用戶編寫的;然而,對於剛開始使用 LaTeX3/TeX 的人來說似乎沒有其他選擇,所以我別無選擇,只能使用我所擁有的東西。這就是我發布此內容的原因。該手冊令人困惑,我想透過問您一些有關語法的簡單問題來消除一些混亂。
我應該提一下,告訴我 LaTeX3 的人也使用其介面為我的原始帖子提供了解決方案。我能夠結合使用該解決方案和手冊來開始了解有關 LaTeX3 語法的一些基本事實。我將談論我已經設法弄清楚的內容,但公平警告,其中一些是基於我自己的推論 - 在 stackexchange 用戶提供的示例的幫助下得出 - 手冊中沒有明確的說明,所以期待錯誤。我想讓你知道,當我有時使用自己的術語時,我並不是混淆問題。很難以結構化的方式談論一個你不完全理解的主題。
另外,由於它的長度,我將其寫為單獨的帖子,而不是評論。提前致謝。
-------------------------------------------------- -------------------------------------------------- -------------------
函數定義。
到目前為止我已經弄清楚了:
除此之外,還使用以下程式碼定義了一個新函數:
\cs_new_<restrictions>:Npn <function name> <function parameters> {<replacement code>}
這是一個 LaTeX 指令,Npn 的作用是告訴介面的「解析器」在程式碼部分\cs_new_<restrictions>
之後應該期望什麼,在本例中,是一個令牌控製字,即一個或多個參數,即和一個令牌list ,即,它取代了函數。\cs_new_<restrictions>: Npn
<function name>
<function parameters>
{<code>}
因此,如果我想定義一個帶有 4 個參數的新函數,我可以使用以下程式碼來實現
\cs_new_<restrictions>:Npn \myfunction #1 #2 #3 #4 {<code>}
類似地,具有 2 個參數的函數的程式碼可能如下所示
\cs_new_<restrictions>:Npn \myfunction #1 #2 {<code>}
當然,我假設 - 如果我錯了,請糾正我 - 空格不是必需的,因為解析器已經被告知如何在以下命令的幫助下相互描述“元”參數( ,<function name>
,<parameters>
{<code>}
NPN。
現在,如果我想取消 #,我可以使用以下通用命令
\cs_new_<restrictions>:Nn <function name>:<function signature> {<code>}
類似的處理,只不過現在解析器期望<function signature>
在 後面有一個類似 Nn、NnN、TnN 或其他的東西<function name>
。
同樣,具有 4 個參數的函數可能如下所示
\cs_new_<restrictions>:Nn \myfunction:NNNN {<code>}
一個有 2 個這樣的參數
\cs_new_<restrictions>:Nn \myfunction:NN {<code>}
裡面還有其他指令l3基礎知識庫用於創建函數,但它們的總體結構似乎基本上相同。唯一的區別在於它們的功能。例如,使用\cs_set...
而不是\cs_new...
使函數成為本地函數而不是全域函數。我可能會寫一篇後續文章,詢問有關 e-type 和 x-type 擴展的更多詳細信息,但現在我認為最好堅持大局。
無論如何,到目前為止是這樣嗎?
好的,繼續。
變數定義。
到目前為止我已經弄清楚了:
所以LaTeX3中有相當多的資料類型,但主要的是代幣列表,字串,整數,序列, 和逗號分隔的列表。它們各自使用自己的縮寫,但一般來說,在定義新變數時,您需要聲明類型並在其後跟上關鍵字,例如新的或者常量取決於您是否正在初始化變數。
例如,如果我想聲明但不初始化一個代幣列表變數我使用程式碼:
\tl_new:N \mytokenList
然後在某處,我可以\mytokenList
使用代碼儲存令牌列表:
\tl_set:Nn \mytokenList {<tokens>}
但是,如果我從一開始就知道要在變數中儲存哪些數據,我可以使用此命令(不適用於序列或者整數)
\tl_const:Nn \mytokenList {<tokens>}
旁白:我注意到即使變數也有「函數簽名」。可能使定義解析機制變得更容易。
在我必須指定我所引用的資料類型之前,這已經是我所能做到的最籠統的了,因為每個資料類型都有自己的關聯操作。
-------------------------------------------------- -------------------------------------------------- -------------------
這就是我到目前為止所擁有的。如果有任何回饋,我將不勝感激。這些東西自己學起來可不容易啊!尤其是對 TeX 的了解很少,所以如果你們中的一些人看到這個並認為“顯然很明顯”,我深表歉意。不管怎樣,再次感謝。
答案1
定義函數的方式主要有兩種:
\cs_new<restrictions>:Npn
\cs_new<restrictions>:Nn
哪裡可以是_protected
,_nopar
或_protected_nopar
.
兩種方法都會檢查N
後面的 - 參數(即單一標記)是否是目前未定義的控制序列(或活動字元),並且全球定義控制序列。
有什麼不同?第一個系列需要在定義控制序列之後,在{
界定函數的「替換文字」之前有一個「參數文字」。
「參數文字」可以是任何標記序列,包括#1
,#2
依此類推直至#9
。然而,為了理解這種自由的全部力量,您需要熟悉 TeXbook 的第 20 章和「定界論證」的概念。
不過,讓我們保持簡單。下面兩段程式碼是完全等價的:
\cs_new:Npn \harry_foo:nn #1 #2 { -#1-#2- }
\cs_new:Nn \harry_foo:nn { -#1-#2- }
因為後者將#1#2
根據要定義的函數的簽名自動提供參數文本,在本例中為:nn
。
n
簽名應由和字元序列(可能為空)組成N
。
\ExplSyntaxOn
請注意,啟動時空格將被忽略,因此
\cs_new:Npn \harry_foo:nn #1 #2 { -#1-#2- }
\cs_new:Npn \harry_foo:nn #1#2 { -#1-#2- }
\cs_new:Npn \harry_foo:nn #1#2{ -#1-#2- }
都是等價的。即使後面可能有一個空格#
,但我不推薦它。
TeX 的語法規則指定何時需要「參數文字」(基本上,在進行\def
或類似的賦值時以及在儲存要定義的巨集的名稱之後)一切直到第一個{
是參數文字的一部分。無法預見參數文字是什麼,因此特殊的p
參數說明符僅表示「所有內容{
」。
只能自動產生諸如#1
、#1#2
等簡單的參數文本,這是在使用第二族時完成的\cs_new<restrictions>:Nn
。
你哪裡錯了?假設您可以T
在簽名中用作說明符。參數說明符T
或在執行F
時新增。\prg_new_conditional<restrictions>:Nnn
另外,您對參數文字的分析是錯誤的,如前所示。
和\cs_set<restrictions>:Npn
呢:Nn
?上面的一切都適用,區別在於要定義的函數不會檢查是否已定義,並且其含義將被默默地覆蓋,但聲明的範圍與當前組一致。通常,\cs_set...
用於需要適應上下文的臨時函數,因此它們的含義不固定。
變數的命名約定推薦他們的名字以l
,g
或開頭c
。實際上,程式碼中使用的變數expl3
應該符合約定;可以使用“正常”名稱,例如要在文件中使用的\myTokenList
類型變數tl
(也可能是)。clist
以 開頭的變數l
應始終在本地(例如)起作用\tl_set:Nn
,而以 開頭的變數應始終在全域(例如)g
起作用。\tl_gset:Nn
以以下開頭的變數c
是常量並且應該是絕不分配值後執行,但僅使用。
可以用以下方式定義常數
\tl_const:Nn \c_harry_foo_tl {<tokens>}
\str_const:Nn \c_harry_foo_str {<tokens>}
\clist_const:Nn \c_harry_foo_clist {<comma list>}
\seq_const_from_clist:Nn \c_harry_foo_seq {<comma list>}
\prop_const_from_keyval:Nn \c_harry_foo_prop {<key-value list>}
\int_const:Nn \c_harry_foo_int {<integer expression>}
\fp_const:Nn \c_harry_foo_int {<fp expression>}
\bool_const:Nn \c_harry_foo_bool {<boolean expression>}
\dim_const:Nn \c_harry_foo_dim {<dimen expression>}
\skip_const:Nn \c_harry_foo_dim {<skip expression>}
\muskip_const:Nn \c_harry_foo_dim {<muskip expression>}
\intarray_const_from_clist:Nn \c_harry_foo_intarray {<comma list>}
\regex_const:Nn \c_harry_foo_regex {<regex>}
\cc_tab_const:Nn \c_harry_foo_cctab {<code>}