LaTeX3 Interface สำหรับฟังก์ชันต่างๆ

Sep 03 2020

ฉันเพิ่งโพสต์คำถามเกี่ยวกับการเขียนมาโครใน TeX ธรรมดาที่จะแก้ไของค์ประกอบในรายการที่ผู้ใช้ระบุ ฉันพูดถึงความไม่ชอบอินเทอร์เฟซของ TeX อย่างไม่เป็นทางการดังนั้นใครบางคนจึงเปลี่ยนฉันเข้าสู่ LaTeX3 ซึ่งควรจะเป็นตามที่คู่มือสัญญาไว้เหมือนภาษาโปรแกรมสมัยใหม่มากกว่า ฉันเพิ่งเริ่มเขียนโปรแกรมใน TeX ดังนั้นจึงเป็นการต่อสู้ที่ยากลำบากในการพยายามทำความเข้าใจคู่มือนี้ ฉันคิดว่าเป็นเพราะคู่มือนี้เขียนขึ้นสำหรับผู้ใช้ TeX ที่มีประสบการณ์ อย่างไรก็ตามดูเหมือนจะไม่มีทางเลือกอื่นสำหรับผู้ที่เพิ่งเริ่มใช้ LaTeX3 / TeX ดังนั้นฉันจึงไม่มีทางเลือกอื่นนอกจากทำงานกับสิ่งที่ฉันมี นั่นคือเหตุผลที่ฉันโพสต์สิ่งนี้ คู่มือมีความสับสนและฉันต้องการที่จะกำจัดความสับสนนั้นโดยการถามคำถามง่ายๆเกี่ยวกับไวยากรณ์

ฉันควรพูดถึงคนที่บอกฉันเกี่ยวกับ LaTeX3 ยังให้วิธีแก้ไขโพสต์ต้นฉบับของฉันโดยใช้อินเทอร์เฟซ ฉันสามารถใช้โซลูชันนี้ร่วมกับคู่มือเพื่อเริ่มหาข้อเท็จจริงพื้นฐานบางประการเกี่ยวกับไวยากรณ์ LaTeX3 ฉันกำลังจะพูดถึงสิ่งที่ฉันได้จัดการเพื่อหาข้อมูล แต่คำเตือนที่เป็นธรรมบางส่วนขึ้นอยู่กับการอนุมานของฉันเอง - วาดด้วยความช่วยเหลือของตัวอย่างที่ผู้ใช้ stackexchange ให้มาไม่ใช่คำแนะนำที่ชัดเจนในคู่มือ ดังนั้นคาดว่าจะผิดพลาด ฉันอยากให้คุณรู้ว่าฉันไม่ได้ทำให้สับสนในบางครั้งที่ฉันใช้คำศัพท์ของตัวเอง เป็นเรื่องยากที่จะพูดถึงเรื่องที่คุณไม่เข้าใจอย่างมีแบบแผน

นอกจากนี้ฉันกำลังเขียนสิ่งนี้เป็นโพสต์แยกต่างหากไม่ใช่ความคิดเห็นเนื่องจากความยาว ขอบคุณล่วงหน้า.

-------------------------------------------------- -------------------------------------------------- -------------------

คำจำกัดความของฟังก์ชั่น

สิ่งที่ฉันได้จัดการจนถึงตอนนี้ :

มีการกำหนดฟังก์ชันใหม่ด้วยรหัสต่อไปนี้:

\cs_new_<restrictions>:Npn <function name> <function parameters> {<replacement code>}

\cs_new_<restrictions>เป็นคำสั่งที่น้ำยางที่ NPN จะมีการบอกอินเตอร์เฟซของ "parser" สิ่งที่มันควรคาดหวังว่าหลังจากที่\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>}

ข้อตกลงที่คล้ายกันยกเว้นตอนนี้ parser คาดหวังสิ่งที่<function signature>คล้ายกัน Nn, NnN, TnN หรือสิ่งอื่น ๆ หลังจาก<function name>นั้น

อีกครั้งฟังก์ชันที่มี 4 อาร์กิวเมนต์อาจมีลักษณะเช่นนี้

\cs_new_<restrictions>:Nn \myfunction:NNNN {<code>}

และหนึ่งกับ 2 อาร์กิวเมนต์แบบนี้

\cs_new_<restrictions>:Nn \myfunction:NN {<code>}

มีคำสั่งอื่น ๆ ในไลบรารีl3basicsสำหรับสร้างฟังก์ชัน แต่โครงสร้างทั่วไปของคำสั่งนั้นดูเหมือนจะเหมือนกัน ความแตกต่างเพียงอย่างเดียวคือในฟังก์ชันการทำงาน ตัวอย่างเช่นการใช้\cs_set...แทนที่จะ\cs_new...ทำให้ฟังก์ชันเป็นแบบโลคัลเมื่อเทียบกับโกลบอล ฉันอาจจะเขียนโพสต์ติดตามเพื่อขอรายละเอียดเพิ่มเติมเกี่ยวกับการขยาย e-type และ x-type แต่สำหรับตอนนี้ฉันคิดว่าดีที่สุดที่จะยึดติดกับภาพรวม

ยังไงก็ตามจนถึงตอนนี้?

เอาล่ะไปต่อ

นิยามตัวแปร

สิ่งที่ฉันได้จัดการจนถึงตอนนี้ :

ดังนั้นจึงมีค่อนข้างไม่กี่ชนิดข้อมูลใน LaTeX3 แต่คนหลักคือรายการโทเค็น , สตริง , จำนวนเต็ม , ลำดับและคั่นด้วยเครื่องหมายจุลภาครายการ แต่ละตัวใช้ตัวย่อของตัวเอง แต่โดยทั่วไปเมื่อกำหนดตัวแปรใหม่คุณจะต้องประกาศประเภทและตามด้วยคำหลักเช่นnewหรือconstขึ้นอยู่กับว่าคุณกำลังเริ่มต้นตัวแปรหรือไม่

ตัวอย่างเช่นหากฉันต้องการประกาศ แต่ไม่ได้เริ่มต้นตัวแปรรายการโทเค็นฉันใช้รหัส:

\tl_new:N \mytokenList

จากนั้นลงไปที่ใดที่หนึ่งฉันสามารถจัดเก็บรายการโทเค็น\mytokenListด้วยรหัส:

\tl_set:Nn \mytokenList {<tokens>}

แต่ถ้าฉันรู้ว่าฉันต้องการเก็บข้อมูลอะไรในตัวแปรจาก get go ฉันสามารถใช้คำสั่งนี้แทนได้ (ไม่ใช้กับลำดับหรือจำนวนเต็ม )

\tl_const:Nn \mytokenList {<tokens>}

นอกเหนือ: ฉันสังเกตเห็นว่าแม้แต่ตัวแปรก็มี "ลายเซ็นฟังก์ชัน" อาจทำให้การกำหนดระบบการแยกวิเคราะห์ง่ายขึ้น

นั่นเป็นเรื่องทั่วไปเท่าที่ฉันจะทำได้ก่อนที่ฉันจะต้องระบุประเภทข้อมูลที่ฉันกำลังอ้างถึงเพราะแต่ละประเภทมีการดำเนินการที่เกี่ยวข้องของตัวเอง

-------------------------------------------------- -------------------------------------------------- -------------------

นั่นคือสิ่งที่ฉันมีจนถึงตอนนี้ ขอขอบคุณสำหรับข้อเสนอแนะ สิ่งนี้ไม่ใช่เรื่องง่ายที่จะเรียนรู้ด้วยตัวคุณเอง! โดยเฉพาะอย่างยิ่งเมื่อมีความรู้เพียงเล็กน้อยเกี่ยวกับ TeX ดังนั้นฉันต้องขออภัยหากบางคนที่คุณกำลังดูสิ่งนี้และคิดว่า "เห็นได้ชัด" ยังไงก็ขอบคุณอีกครั้ง

คำตอบ

2 egreg Sep 03 2020 at 17:30

มีสองวิธีหลักในการกำหนดฟังก์ชัน:

\cs_new<restrictions>:Npn

\cs_new<restrictions>:Nn

ที่สามารถ_protected, หรือ_nopar_protected_nopar

ทั้งสองวิธีตรวจสอบว่าN-argument (นั่นคือโทเค็นเดียว) ต่อไปนี้เป็นลำดับควบคุม (หรืออักขระที่ใช้งานอยู่) ที่ไม่ได้กำหนดไว้ในปัจจุบันและกำหนดลำดับการควบคุมแบบโกลบอล

อะไรคือความแตกต่าง? ที่ตระกูลแรกต้องการหลังจากกำหนดลำดับการควบคุมแล้ว "ข้อความพารามิเตอร์" ก่อนการ{คั่น "ข้อความแทนที่" ของฟังก์ชัน

“การพารามิเตอร์ข้อความ” สามารถลำดับใด ๆ ของสัญญาณรวมทั้ง#1, #2และอื่น ๆ #9ขึ้นไป อย่างไรก็ตามเพื่อที่จะได้รับประโยชน์อย่างเต็มที่จากเสรีภาพนี้คุณจำเป็นต้องทำความคุ้นเคยกับบทที่ 20 ของ TeXbook และแนวคิดของ "อาร์กิวเมนต์ที่ใช้ตัวคั่น"

ขอให้มันง่ายแม้ว่า โค้ดสองส่วนต่อไปนี้เทียบเท่ากันทั้งหมด:

\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>}