Illegal Parameter Number in Definition of Test. N L.73 End{itemize}
LaTeX3: Programming in LaTeX with Ease
Many people view LaTeX every bit a typesetting language and overlook the importance of programming in certificate generation procedure. As a matter of fact, many large and structural documents tin benefit from a programming backend, which enhances layout standardization, symbol coherence, editing speed and many other aspects. Despite the fact the standard LaTeX (LaTeX2e) is already Turing complete, which means information technology is capable of solving whatsoever programming job, the blueprint of many programming interfaces is highly inconsistent due to compatibility considerations. This makes programming with LaTeX2e very challenging and deadening, even for seasoned estimator programmers.
To make programming in LaTeX easier, the LaTeX3 interface is introduced, which aims to provide modern-programming-linguistic communication-like syntax and library for LaTeX programmers. Unfortunately, there is piffling cloth regarding this wonderful linguistic communication. When I started learning it, I had to go through its complex technical manual, which is time-consuming. Therefore, I decide to write a LaTeX3 tutorial that is easy-to-sympathise for generic programmers.
- Preface
- Why LaTeX3?
- Handle macro expansion like a boss
- Messy interfaces in LaTeX
- Goals of LaTeX3
- LaTeX3 Naming Conventions (I-1)
- Category code and command names
- Name of variables
- Proper noun of functions
- Reading LaTeX3 Documentation
- Role documentation
- Scratch variables
- Constants
- Summary
- Functions & Variables
- Defining and using variables
- Declaring functions (Four-iii.2)
- Copying the definition of existing functions
- Showing the definition of functions
- Summary
- Macro Expansion Control (V)
- Method 1: change argument specification of functions
- Method 2: use
\exp_args:Nfunctions (5.four, V.5, 5.6) - Summary
- LaTeX3: Token List and String
- Token list (7)
- Constructing a command in token list
- Student management arrangement
- String (Eight)
- Vertical text node in TikZ
- Token list (7)
- LaTeX3: Numeric Evaluation and Boolean Logic
- Boolean logic (Thirteen)
- Integer arithmetic
- Implementing modulo operation
- Implementing Caesar null
- Integer-based loop and condition
- Computing the greatest mutual divisor (non-recursive)
- Computing the greatest common divisor (recursive)
- Pupil direction organization
- Three means to implement nested loop
- Drawing a square number grid in TikZ
- Floating point number (XXIII) and dimension (XX)
- Drawing a rectangular number filigree in TikZ
- Drawing points on a circle and connect them pairwise
- LaTeX3: Data Structure
- Queue (10, XV)
- Student direction system
- Bracket matching
- Dictionary (XVII)
- Arabic numerals to English (0-99)
- Queue (10, XV)
- LaTeX3: Regular Expression (XXVIII)
- Check if a character is Chinese
- Substitute a command with another
- Generate TikZ motion picture based on a template
- LaTeX3: File I/O (Nineteen)
- Writing to a file
- Reading and parsing comma-separated file
- Memo
- End Note
Preface
Why LaTeX3?
Handle macro expansion similar a dominate
Fundamentally, works past doing macro substitution: commands are substituted by their definition, which is subsequently replaced by definition's definition, until something irreplaceable is reached (e.1000. text). For example, in the following case,
\myname is substituted by \mynameb ; \mynameb is then substituted past \mynama ; and eventually, \mynamea is replaced by John Doe, which cannot be expanded anymore. This process is called expansion.
\newcommand { \mynamea }{John Doe} \newcommand { \mynameb }{ \mynamea } \newcommand { \myname }{ \mynameb } My proper noun is \myname. Nigh command nosotros use everyday has complicated definitions. During compilation, they will be expanded recursively until text or
primitive is reached. This process sounds pretty straightforward, until we want to change the order of macro expansion.
Why do we need to change the order of macro expansion? Allow's consider the \uppercase macro in , which turns lowercase letters into upper-case letter ones. Only consider the following case, where we endeavor to apply
\upper-case letter to letters abcd and a command \cmda . Since \cmda expands to abcd, we expect the outcome to be ABCDABCD. In reality, gives us
ABCDabcd, which means the content of \cmda is unchanged.
\newcommand { \cmda }{abcd} \uppercase {abcd\cmda } %ABCDabcd How tin this happen? During the expansion of \uppercase , the command scans the particular inside the adjacent curly braces one by one. If an English letter is encountered, an uppercase analogue is left in the output stream; otherwise, the original item is left in the input stream. When information technology's \cmda 's turn, because information technology is a command instead of a letter, it is left untouched in the output stream, which is expanded to abcd afterward.
What if we want to capitalize everything within the curly braces? That would crave the macro \cmda to exist expanded before \capital letter , or equivalently, changing the order of macro expansion. The classical manner of doing so in is via
\expandafter . Unfortunately, the usage of \expandafter is extremely complicated1: in a string of n tokens2, to expand the ithursday token, there must exist \(2^{northward-i}-1\) \expandafter 's earlier the ith token. Below is a instance of how bad this can look like:
\documentclass {article} \begin{document} \def\x#one#2#three#iv{ % \def\arga {#2} % \def\argb {#3} % \def\argc {#4} % \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter#1% \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter { \expandafter\expandafter\expandafter\arga\expandafter\expandafter\expandafter } % \expandafter\expandafter\expandafter { \expandafter\argb\expandafter } \expandafter { \argc }} \def\y#1#2#three{ \detokenize {#1#ii#iii}} \x\y {arg1}{arg2}{arg3} \end{document} Conspicuously, it is nowhere well-nigh decency: the excessive number of \expandafter 's are sometimes referred to as " \expandafter purgatory". As a result, one of the features of is to provide simple and reliable expansion control.
Messy interfaces in LaTeX
Believe it or not, is able to attain everything other generic programming languages tin practice (e.g. C++, Python, Coffee)3. Withal, the part call conventions can exist wildly distinct across unlike tasks; some similar functionalities can be independently implemented various packages. Here are some examples:
- File read
\newread\file \openin\file=myfilename.txt \loop\unless\ifeof\file \read\file to\fileline % Reads a line of the file into \fileline % Practise something with \fileline \repeat \closein\file - File write
\newwrite\file \immediate\openout\file=myfilename.txt \firsthand\write\file {A line of text to write to the file} \firsthand\write\file {Some other line of text to write to the file} \closeout\file - Integer arithmetics
\newcount\mycount \mycount=\numexpr(25+5)/three\relax \advance\mycount by -3 \multiply\mycount by 2 - Condition
% command-related if statement \ifx\mycmd\undefined undefed \else \if\mycmd1 defed, 1 \else defed \fi \fi % number-related if argument \ifdim#1pt=#2pt Equal.\\ \else % Not equal.\\ \fi % -
Loop
% use \loop \newcount\foo \foo=10 \loop \message { \the\foo } \accelerate \foo -1 \ifnum \foo>0 \repeat % while loop (provided by `ifthen` parcel) \newcounter {ct} \setcounter {ct}{1} \whiledo { \value {ct} < five} % { \the\ct \stepcounter {ct} % } % for loop (provided by `ifthen` package) \forloop {ct}{ane}{ \value {ct} < 5} % { % \the\ct }
These inconsistencies fix a high bar for new users and make it hard to connect multiple components together, even for experienced
programmers. Therefore,
aims to provide standardized programming interfaces and documentation for the language.
Goals of LaTeX3
LaTeX3 Naming Conventions (I-ane)
In the following lawmaking snippet, we declare a variable \vara and a office \cmda . The way we distinguish between a variable and a function is merely by judging whether the command absorbs arguments or not. Notwithstanding, the fact that they are all called "commands" and created with \newcommand reflects that they are fundamentally the same for system.
\newcommand { \vara }{this is a variable} \newcommand { \cmda }[1]{this is a control: #1} From users' perspective, it is important to dissever variables from functions considering their usages are different. Therefore, our simply pick is to encode this information into the proper name of commands, so that users can differentiate variables and functions with footling effort. This is why we need to introduce the naming convention. Before actually elaborating on
naming style, I would similar to brand a minor diversion and introduce category code commencement.
Category code and command names
In , every grapheme that nosotros enter is associated with a category code. Standard category code assignment can be seen in the post-obit tabular array:
| Category lawmaking | Description | Standard |
|---|---|---|
| 0 | Escape character-tells | \ |
| 1 | Starting time a group | { |
| 2 | End a grouping | } |
| iii | Math shift-switch in/out of math mode | $ |
| 4 | Alignment tab | & |
| 5 | Cease of line | ASCII code thirteen (\r) |
| six | Macro parameter | # |
| 7 | Superscript for typesetting math | ^ |
| viii | Subscript for typesetting math | _ |
| 9 | Ignored character | ASCII 0 \0 |
| 10 | Spacer | ASCII codes 32 (space) and 9 (tab character) |
| 11 | Letter | A…Z, a…z |
| 12 | Other | 0…ix plus @,.;?" and many others |
| 13 | Active character | Special category code for creating single-character macros such as ~ |
| 14 | Comment character-ignore everything that follows until the cease of the line | % |
| fifteen | Invalid character, non allowed to announced in the .tex input file | ASCII code 127 (\127) |
When run across a character with category 0 (due east.1000.
\), information technology continue to scan the subsequent characters, which eventually results in one of the following4:
- Multi-alphabetic character commands: the character following immediately afterward the escape character has category code 11 (letter). All subsequent characters that take category code 11 are considered to form the name of a command (control word).
will stop looking for characters that form part of a command name when information technology detects any character that does not have category code 11—such every bit a infinite graphic symbol with category code 10.
- Unmarried-letter of the alphabet commands: the character following immediately after the escape character does non have category code 11.
This machinery shows why nosotros cannot put Arabic numerals or punctuations into command names. Interestingly, the category code associated with a detail grapheme is mutable. That's the reason why most hidden commands in have
@ in their names, considering the category lawmaking of @ is ordinarily 12 (other), which is illegal in command names. In guild to access these commands, we need to call \makeatletter , which just as the name suggests, changes the category code of @ to 11 (alphabetic character). Later using subconscious commands, we need to call \makeatother to reset category code assignment.
In , command names are made up of English messages, underline (
_) and colon(:). In order to activate the unlike naming scheme of , one needs to enter
mode with
\ExplSyntaxOn and exits with \ExplSyntaxOff . In general, \ExplSyntaxOn will make the following changes:
- The category code of
_and:will exist set to 11 (letter of the alphabet) - All spacers and line breaks will exist ignored
Name of variables
- Public variables:
\<telescopic>_<module>_<description>_<blazon> -
Private variables:
\<scope>__<module>_<description>_<blazon> - Telescopic
-
l: local variable -
g: global variable -
c: constant
-
- Module: the name of module
- Clarification: the description of variable
- Common types:
-
clist: comma separated list -
dim: dimension -
fp: floating bespeak number -
int: integer -
seq: sequence (similar toqueuein other programming languages) -
str: string -
tl: token listing -
bool: boolean -
regex: regular expression -
prop: property list (similar todictin Python) -
ior/iow: IO read/write
-
- Examples
\g_my_var_int \l__testa_clist \c_left_brace_str
Proper noun of functions
When we write C/C++ code, we need to explicit declare the type of each arguments, for example:
int mult ( int a , int b ){ render a * b ; } To increment the readability of code, a similar design is adopted: detailed information nearly each argument is specified in
<arg-spec>.
- Public functions:
\<module>_<description>:<arg-spec> -
Private functions:
\__<module>_<description>:<arg-spec> - Module: the name of module
- Description: the clarification of variable
- Statement specification: detailed description of each argument encoded in a string
-
northward: receives a token list (for at present, nosotros can treat token lists every bit contents enclosed by curly braces) -
N: receives a command, laissez passer the command itself -
5:receives a command, pass the value of the command -
o:similar ton, but expands the token list once -
x:similar tox, but expands the token list recursively -
T/F: normally used inifstatements: the correspondingTorFcode is executed based on the status -
p: parameter list, unremarkably consists of#1#2… -
c: receives a token list, pass the command named after the token list (similar to\csname…\endcsname)
-
It is worth mentioning that all these naming conventions are merely a suggestion: in most cases, will not prase the name of the command to acquire information. There is essentially no hard restriction on the proper name of variables and functions: the telescopic or public/private identifiers are purely for the sake of users, not the
compiler. However, using consistent naming convention can increase lawmaking readibility.
Reading LaTeX3 Documentation
At this moment, near materials are compiled in The LaTeX3 Interfaces. The first chapter of this document briefly introduces the fundamentals of
. Each subsequent chapter elaborates on a module of
. Functions are grouped in different sections based on their purposes.
Part documentation
Most items in sections are detailed descriptions almost functions. Have
\tl_set :Nn as an instance:
- All variants of a function is listed in box on the left. According to the screenshot to a higher place, the post-obit functions are provided past
5:
\tl_set :Nn \tl_set :NV \tl_gset :Nx \tl_gset :cx
- The syntax of a function is on the top-right.
- The detailed description of a function is on the bottom-correct.
Scratch variables
Many modules come with predefined "scratch variables" then that users exercise not accept to declare any variable when the code is small-scale. In every chapter, their is a dedicated section to certificate what scratch variables (as well equally constants) are divers.
When writing serious code, it is recommended to avoid scratch variables to maximize compatibility.
Constants
Some libraries come up with pre-divers constants. They will exist introduced in a dedicated section.
Summary
Functions & Variables
Defining and using variables
Each module of may use different variable construction format. Therefore, information technology is important to initialize each variable blazon with its dedicated office. In general, office ends in
new are for declaring new variables; functions that contains set or gset are for modifying variables' states; functions that contains go are for acquiring variables' states.
Consider two specific cases \tl_set :Nn and \tl_gset :Nn , which are both used for modifying a token list's value. What are the differences? As it turns out, the letter one thousand in gset stands for "global": normally, only sets the value of a variable locally, i.east. within its own grouping. That is to say, the modified value will not be visible outside the group. Therefore, if we wish a change to be attainable for all functions, we demand to employ
gset variants.
A concrete case:
\ExplSyntaxOn \tl_set :Nn \l_tmpa_tl {A} \group_begin : \tl_set :Nn \l_tmpa_tl {B} \par value~inside~group:~\tl_use :N \l_tmpa_tl \group_end : \par value~outside~group:~\tl_use :N \l_tmpa_tl
\tl_set :Nn \l_tmpb_tl {A} \group_begin : \tl_gset :Nn \l_tmpb_tl {B} \par value~within~group:~\tl_use :North \l_tmpb_tl \group_end : \par value~exterior~group:~\tl_use :North \l_tmpb_tl \ExplSyntaxOff The output is:
value inside group: B value outside grouping: A value inside grouping: B value exterior group: B Information technology tin can exist seen that \tl_set :Nn only modifies the value inside the group and leaves the value exterior untouched; while \tl_gset :Nn changes both values.
In full general, the principles of using variables are:
- Determine the correct variable type and call the corresponding declaration function (if the number of needed variables is small, conside using scratch variables).
- Determine the scope and proper noun the variable according to
naming conventions.
- Employ
setorgsetfunctions to alter a variable'due south value. - Use respective library functions to operate on variables.
Declaring functions (IV-3.2)
In ,
\cs_set :Npn is usually used for declaring functions. Apart from it, at that place are likewise other three functions that serve this task, namely \cs_set_nopar :Npn , \cs_set_protected :Npn and \cs_set_protected_nopar :Npn . Considering \cs_set :Npn is used in most cases, we mainly put our focus on it. In fact, their usages are extremely close.
The procedure of declaring a function is every bit follows:
- Determine the number of arguments and their respective types (
macros can accpet at nearly 9 arguments)
- Name the function according to
naming convention and define the office with one of functions above.
For example, suppose we are to create a office that concatenates its ii arguments with comma. Therefore, nosotros know the number of arguments is 2, and both arguments are of type n. As a effect, we tin proper noun the function \my_concat :nn . We can define \my_concat :nn like then:
\ExplSyntaxOn %ascertain \my_concat:nn \cs_set :Npn \my_concat :nn #ane#2 { #1,~#2 } %use \my_concat:nn \my_concat :nn {a}{b} %effect: a, b \ExplSyntaxOff Copying the definition of existing functions
Sometimes, it is convenient to re-create the definition of existing functions. This tin can be achieved past invoking \cs_set_eq :NN . In the following case, nosotros create a version of
\department function: \my_section :due north , and so use it to declare a new "Hello Globe" section. As we volition show later, if a office is declared using naming convention, its macro expansion command volition be more convenient.
\ExplSyntaxOn \cs_set_eq :NN \my_section :n \department \my_section :n {Hello~Earth} \ExplSyntaxOff Showing the definition of functions
It is possible to show the definition of a part past using \cs_meaning :N . For instance, \cs_meaning :N \section gives:
\long macro:->\@startsection {section}{1}{\z@ }{-iii.5ex \@plus -1ex \@minus -.2ex}{two.3ex \@plus .2ex}{\normalfont \Large \bfseries } Summary
Macro Expansion Control (V)
Back to the \capital letter example above:
\newcommand { \cmda }{abcd} \uppercase {abcd\cmda } %ABCDabcd To bear witness how macro expansion can be resolved with , nosotros first create a
equivalent for the part, namely
\my_uppercase :n . At this point, the behavior of \my_uppercase :n is the same equally \capital letter .
\newcommand { \cmda }{abcd} \ExplSyntaxOn \cs_set_eq :NN \my_uppercase :north \capital \my_uppercase :n {abcd\cmda } % ABCDabcd \ExplSyntaxOff At present, nosotros discuss ii ways to manipulation macro expansion so that the output becomes ABCDABCD (instead of ABCDabcd).
Method 1: modify statement specification of functions
At this moment, the argument blazon of \my_uppercase :n is n, which indicates an unexpanded token list. As a thing of fact, every role has due north or N blazon arguments when get-go declared. Now, we would like to alter to blazon signature to x, i.east. expanding everything in the token list recursively before beingness passed to \my_uppercase . In , in that location is a office dedicated to irresolute the argument specification of other functions:
\cs_generate_variant :Nn . It takes two arguments: the first i is the part we would similar to alter; the second 1 is the new argument specification. Given \my_uppercase :due north , nosotros can generate \my_uppercase :x with the help of \cs_generate_variant :Nn and and then invoke the new function variant.
\newcommand { \cmda }{abcd} \ExplSyntaxOn \cs_set_eq :NN \my_uppercase :n \uppercase \cs_generate_variant :Nn \my_uppercase :n {x} \my_uppercase :ten {abcd\cmda } % ABCDABCD \ExplSyntaxOff Important Notice: \cs_generate_variant :Nn but works for functions post-obit naming convention.
Method 2: utilise \exp_args:N functions (V.four, V.five, 5.vi)
Declaring new variants with \cs_generate_variant :Nn frequently may be a bit inconvenient. Fortunately, provides a series of
\exp_args :North functions that tin facilitate macro expansion control when the number of arguments in small.
In short, if nosotros employ \cs_generate_variant :Nn to generate and use a new variant part:
\cs_generate_variant :Nn \func :abcd {efgh} \func :efgh {i}{two}{three}{iv} It volition be equivalent to the following \exp_args :N office call:
\exp_args :Nefgh \func :abcd {i}{two}{three}{4} Using \exp_args :N functions, nosotros tin also fully expand the argument for \my_uppercase :due north :
\newcommand { \cmda }{abcd} \ExplSyntaxOn \cs_set_eq :NN \my_uppercase :north \capital \exp_args :Nx \my_uppercase :n {abcd\cmda } %ABCDABCD \ExplSyntaxOff It is worth noticing that \exp_args:N functions tin can be used to command expansion partially. For case, if a function takes three arguments, and we utilize \exp_args:Nc to it, then only the start argument will exist modified, while the remainder are left untouched. In the case below, we apply c type exansion to the first argument of \NewDocumentCommand from xparse parcel, which allows the states to declare a command named later the content stored in a variable.
% load `xparse` package for this instance (will be automatically loaded for newer TeX versions) \ExplSyntaxOn % shop command name in a variable \tl_set :Nn \l_tmpa_tl {mycmd} % use \exp_args:Nc to aggrandize the first arguemnt merely % which allows us to declare a command using the content of \l_tmpa_tl \exp_args :Nc \NewDocumentCommand { \l_tmpa_tl }{m}{ \par y'all~entered~#1 } % y'all entered something \mycmd {something} \ExplSyntaxOff Summary
LaTeX3: Token List and Cord
Token list (Seven)
Everything that is entered in a tex file can exist interpreted as a token. Therefore, token lists are collections of all objects recognized past the compiler. In
, token lists are the virtually fundamental and oftentimes used variable type.
Constructing a command in token list
Suppose nosotros would similar to call \section* {<title>} , and the <title> is stored in the token list variable \l_tmpa_tl . We can do it equally follows:
\ExplSyntaxOn % put the title in \l_tmpa_tl \tl_set :Nn \l_tmpa_tl {My~Championship} % construct the control in \l_tmpb_tl \tl_set :Nx \l_tmpb_tl { \exp_not :N \section* { \l_tmpa_tl }} \cs_meaning :N \l_tmpb_tl % macro:->\section *{My Title} % identify the content of \l_tmpb_tl into the input stream \tl_use :Due north \l_tmpb_tl \ExplSyntaxOff In this case, nosotros are using \tl_set :Nx , which ways everything inside the curly braces will be expanded completely and recursively. As a event, in the definition of \l_tmpb_tl , the variable name \l_tmpa_tl volition be replaced by its value. Since we do not want to expand the definition of \section , nosotros use \exp_not :N to suppress its expansion.
Student management system
Suppose we want to gear up an internal student management system in . Nosotros would similar to implement the following three commands:
-
\student: add a new student into the system -
\allstudent: bear witness all students, separated past commas -
\thestudent: takes 1 argument and shows the \(i\)-th student
We will reuse this instance many times throughout this tutorial, but with different implementation techniques. Here, we use token list related functions to implement the iii commands above.
\documentclass {article} \usepackage [T1] {fontenc} \usepackage {expl3} \usepackage {amsmath, amssymb} \brainstorm {document} \ExplSyntaxOn % stores all students, separated by commas \tl_new :N \l_student_comma_tl % stores the name of each student \tl_new :Due north \l_student_group_tl \newcommand { \student }[one]{ #ane% outputs student'south name % bank check if \l_student_comma_tl is empty % this is a conditional branch statement % which nosotros volition discuss in the subsequent sections \tl_if_empty :NTF \l_student_comma_tl { % if empty, do not prepend comma earlier name \tl_put_right :Nn \l_student_comma_tl {#ane} } { % otherwise, prepend comma earlier name \tl_put_right :Nn \l_student_comma_tl {,~#1} } % put pupil name in a group and % store it in \l_student_group_tl \tl_put_right :Nn \l_student_group_tl {{#1}} } \newcommand { \allstudent }{ % outputs \l_student_comma_tl \tl_use :N \l_student_comma_tl } \newcommand { \thestudent }[1]{ % outputs the #ane-th token in \l_student_group_tl \tl_item :Nn \l_student_group_tl {#1} } \ExplSyntaxOff % John and Lisa and David and Emily \student {John} and \pupil {Lisa} and \student {David} and \student {Emily} % John, Lisa, David, Emily \par\allstudent % Emily and David and Lisa and John \par\thestudent {4} and \thestudent {3} and \thestudent {2} and \thestudent {1} \end {document} - In this solution, we store each name twice in
\l_student_comma_tland\l_student_group_tl.\l_student_comma_tlstores the name of all students, joined past commas, which is used by\allstudent.\l_student_group_tlallows index access for student names, for each student is saved equally a group in the token list. Every time one calls\student, the new student name volition exist inserted into the two token lists. - When inserting into
\l_student_comma_tl, there is no need to prepend comma if it is the first name. Therefore, nosotros need to use the conditional argument\tl_if_empty :NTFto specify this behavior. - Find that we surround the educatee name with curly braces when inserting into
\l_student_group_tl, which effectively encapsulates each student name within a group. As a result, when calling\tl_item :Nn, the entire grouping volition be returned, which allows us to call up the student name equally a whole.
String (Eight)
A close relative to token listing is string. When we apply \tl_use :Due north to a token list variable, it is equivalent to typing its content directly in the tex file. If we run the following example
\newcommand { \cmda }{efgh} \ExplSyntaxOn \tl_set :Nn \l_tmpa_tl {abcd\cmda } \tl_use :Northward \l_tmpa_tl %abcdefgh \ExplSyntaxOff then we will become abcdegfh in the document output, considering \cmda is stored equally a command in \l_tmpa_tl , which is afterwards expanded to efgh. Notwithstanding, If we run the aforementioned instance with string type, and then everything inside the cord variable will be interpereted every bit text instead of command of special character. Consequently, the output in the document becomes abcd\cmda.
\newcommand { \cmda }{efgh} \ExplSyntaxOn \str_set :Nn \l_tmpa_str {abcd\cmda } \str_use :Due north \l_tmpa_str %abcd\cmda \ExplSyntaxOff We can use \tl_to_str :northward to convert a token list into a string. It is possible to transform strings back to token lists with \tl_rescan :nn six.
Vertical text node in TikZ
\ExplSyntaxOn \cs_set :Npn \my_vert_str :n #i { % shop argument every bit string \str_set :Nn \l_tmpa_str {#ane} % traverse the string \str_map_inline :Nn \l_tmpa_str { % center each character at their own line \centering ##one \par } } % declare latex interface \newcommand { \vertstr }[1]{ \my_vert_str :n {#1} } \ExplSyntaxOff \begin {tikzpicture} \node [draw=black, text width=1cm] { \vertstr {ab$ c $d~\\\\ }}; \end {tikzpicture} Output:
's cord method is implemented with
\detokenize . As a issue, neither \tl_to_str :n nor \str_set :Nn can guarantee that the cord output is exactly the aforementioned equally users' input. For example, \detokenize adds an actress infinite later on commands. That is, \verb|abc| becomes \verb |abc|. This can be tricky in some scenarios.
Very oftentimes, nosotros need to compare if ii token lists or strings are equal. Since the token list library and string library both take their ain equality functions, we tin choose betwixt \tl_if_eq : (from token listing library) and \str_if_eq : (from cord library). Unless information technology is absolutely necessary, it is recommended to use cord library'south comparision functions. That is because \tl_if_eq : non only checks if the characters are the same, but information technology also checks if the category code of each graphic symbol is the same. Equally a result, two seemingly identical variables can issue in Fake outcome when using \tl_if_eq : .
LaTeX3: Numeric Evaluation and Boolean Logic
This department mainly consists of lawmaking snippets with detailed comments, for the underlying methodology of these topics are similar to other programming languages. Therefore, it is more than benign to be able to locate the correct APIs in documentation.
Boolean logic (XIII)
\ExplSyntaxOn % declare new boolean value \bool_new :Due north \l_my_bool % set up to true \bool_set_true :N \l_my_bool % set to false \bool_set_false :N \l_my_bool % boolean based conditional statement \bool_if :nTF { \l_my_bool } {true} {false} %fake % boolean based while loop \bool_do_while :nn { \l_my_bool } {} % boolean based until loop % boolean functions support C/C++ % way !, || and && operations \bool_do_until :nn {!\l_my_bool } {} \ExplSyntaxOff Integer arithmetic
Implementing modulo functioning
It is worth noticing that already has
\int_mod :nn . This sample is for demonstration purposes.
\ExplSyntaxOn \cs_set :Npn \my_mod :nn #1#2 { % shop #1//#ii in \l_tmpa_int \int_set :Nn \l_tmpa_int { \int_div_truncate :nn {#1}{#two} } % compute (#one)-\l_tmpa_int*(#2) % brand sure to environment operands with parentheses % and then that when #1 is an expression (e.g. 3-2) % the order of arithmetic volition non change \int_eval :n { (#ane) - \l_tmpa_int * (#2) } } % define LaTeX interface \newcommand { \mymod }[two]{ \my_mod :nn {#1} {#2} } \ExplSyntaxOff \mymod {v}{3} \mymod {6}{three} \mymod {7}{1+two} %201 Implementing Caesar zero
Caesar goose egg is a classic exchange zero in cryptography.
\ExplSyntaxOn \cs_set :Npn \my_caesar_cipher :n #1 { % transform #one to lower case and store in \l_tmpa_str \str_set :Nx \l_tmpa_str { \tl_lower_case :n {#one}} % clear \l_tmpb_str to store results \str_clear :North \l_tmpb_str % \str_map_inline:Nn traverses the string % and pass each character as first statement \str_map_inline :Nn \l_tmpa_str { % `##1 gives the ASCII code of ##1 % 91 is the ASCII code of 'a' % this allows us to compute the get-go of ##ane \int_set :Nn \l_tmpa_int { \int_eval :n {`##1 - 97} } % suppose the shifting of our Ceaser zip is 3 \int_set :Nn \l_tmpb_int { \int_mod :nn { \l_tmpa_int + three}{26} } % place new grapheme in \l_tmpb_str \str_put_right :Nx \l_tmpb_str { % this function generates a grapheme given % character code and category code % because we are dealing with English language letters % the category code is 11 \char_generate :nn { \l_tmpb_int + 97}{eleven} } } % outputs \l_tmpb_str \str_use :N \l_tmpb_str } \my_caesar_cipher :n {helloworld} %khoorzruog \ExplSyntaxOff Integer-based loop and condition
Mutual integer-based conditional statements:
-
\int_compare_p :series: compare ii integers given a relation and returns a boolean value -
\int_compare :serial: compare two integers given a relation and executeTlawmaking orFcode based on the issue
Mutual integer-based loops:
-
\int_do_while :series -
\int_do_until :series -
\int_step_function :,\int_step_inline :and\int_step_variable :
ane, 2 are often used with \int_incr :N ( \int_gincr :N ) and \int_decr :North ( \int_gdecr :N )
One may have noticed that almost integer related comparions provide :n and :nNn` variants. They are different in the following ways:
-
:nNnjust supports 3 types of comparsion:<,>and= - In addition to
<,>and==,:due northalso supports>=,<=and!= -
:nsupports chained comparison:a<b<c - The speed of
:nis about one fifth of the speed of:nNn
\int_compare_p :nNn { \l_tmpa_int } < { \l_tmpb_int } % is equivalant to \int_compare_p :northward { \l_tmpa_int < \l_tmpb_int } Computing the greatest common divisor (non-recursive)
We implement the Eulidean algorithm to compute the greatest common divisor.
\ExplSyntaxOn % declare one more scratch variable \int_new :Due north \l_tmpc_int \cs_set :Npn \my_gcd :nn #1#ii { % put #1 in \l_tmpa_int \int_set :Nn \l_tmpa_int {#i} % put #ii in \l_tmpb_int \int_set :Nn \l_tmpb_int {#two} % loop until \l_tmpb_int equals 0 \int_do_until :nNnn { \l_tmpb_int } = {0} { % update three variables \int_set :Nn \l_tmpc_int { \l_tmpb_int } \int_set :Nn \l_tmpb_int { \int_mod :nn { \l_tmpa_int }{ \l_tmpb_int } } \int_set :Nn \l_tmpa_int { \l_tmpc_int } } % outputs \l_tmpa_int \int_use :N \l_tmpa_int } \my_gcd :nn {vi}{3}~\my_gcd :nn {270}{192} % 3 6 \ExplSyntaxOff Computing the greatest common divisor (recursive)
Equally mentioned above, compared to gset functions, set functions only modify variable values within the current grouping. Using this machinery, information technology is possible to imitate a callstack in other programming languages to implement recursive algorithms. In the following example, it is shown that local varialbles will not be modified by subroutines considering each set role is guarded by \group_begin : and \group_end : .
\ExplSyntaxOn \cs_set :Npn \my_gcd_recursive :nn #1#2 { \group_begin : % all variable assignments volition exist constrained in this group \int_compare :nNnTF {#2} = {0} { \int_gset :Nn \g_tmpa_int {#one} } { \int_set :Nn \l_tmpa_int { \int_mod :nn {#ane}{#ii}} \int_set :Nn \l_tmpb_int { \int_div_truncate :nn {#1}{#2}} \exp_args :Nnx \my_gcd_recursive :nn {#2} { \int_use :Northward \l_tmpa_int } % output debug message \par $ \int _use:North \fifty _tmpb_int \times # 2 + \int _use:N \l _tmpa_int = # 1 $ } \group_end : } \my_gcd_recursive :nn {12546}{156} \par $ \operatorname {gcd} ( 12546 , 156 ) = \int _use:N \k _tmpa_int $ \ExplSyntaxOff Output:
3 × 6 + 0 = 18 1 × xviii + 6 = 24 ii × 24 + 18 = 66 ii × 66 + 24 = 156 80 × 156 + 66 = 12546 gcd(12546; 156) = 6 Student management system
At present, we implement the aforementioned student management organisation with integer related functions.
\ExplSyntaxOn % used to store the proper name of each student \tl_new :N \l_student_group_tl \newcommand { \student }[ane]{ #ane% outputs student proper noun % put student name in group and so % insert into \l_student_group_tl \tl_put_right :Nn \l_student_group_tl {{#ane}} } \newcommand { \allstudent }{ %\tl_count:N returns the length of a token listing %\int_step_inline:nn traverses all integers in % the range (one, #one) and pass the loop variable equally % #1 \int_step_inline :nn { \tl_count :N \l_student_group_tl }{ % become the ##1-th element from \l_student_group_tl \tl_item :Nn \l_student_group_tl {##i} % make up one's mind if information technology is the last chemical element % otherwise, append comma \int_compare :nNnTF {##i} = { \tl_count :N \l_student_group_tl } {} {,~} } } \newcommand { \thestudent }[1]{ % outputs the #i-thursday particular in \l_student_group_tl \tl_item :Nn \l_student_group_tl {#1} } \ExplSyntaxOff % John and Lisa and David and Emily \student {John} and \student {Lisa} and \student {David} and \pupil {Emily} % John, Lisa, David, Emily \par\allstudent % Emily and David and Lisa and John \par\thestudent {iv} and \thestudent {3} and \thestudent {2} and \thestudent {1} Iii ways to implement nested loop
\ExplSyntaxOn \par \int_step_variable :nNn {4} \l_tmpa_tl { \int_step_variable :nNn {4} \l_tmpb_tl { (\l_tmpa_tl,\l_tmpb_tl) } } \par \int_step_inline :nn {4} { \int_step_inline :nn {4} { (#ane,##one) } } \par \int_set :Nn \l_tmpa_int {i} \int_do_while :nNnn { \l_tmpa_int } < {5} { \int_set :Nn \l_tmpb_int {1} \int_do_while :nNnn { \l_tmpb_int } < {5} { (\int_use :N \l_tmpa_int,\int_use :N \l_tmpb_int) \int_incr :N \l_tmpb_int } \int_incr :Northward \l_tmpa_int } \ExplSyntaxOff Output:
(1,ane)(1,ii)(ane,3)(1,4)(2,1)(2,ii)(2,3)(2,4)(3,i)(3,2)(iii,3)(three,4)(4,1)(four,two)(4,3)(iv,4) (1,1)(1,2)(one,three)(i,4)(ii,1)(2,2)(2,three)(2,iv)(3,1)(iii,2)(3,iii)(3,4)(four,1)(four,ii)(four,3)(4,iv) (one,1)(1,2)(1,3)(1,iv)(2,1)(2,2)(ii,3)(2,iv)(iii,1)(3,2)(3,iii)(3,4)(four,1)(4,2)(4,iii)(4,4) Drawing a square number grid in TikZ
\tikzset { mynode/.manner={ minimum height=1cm, minimum width=1cm, draw, anchor=north west } } \ExplSyntaxOn \brainstorm {tikzpicture} \int_step_inline :nn {half-dozen} { \int_step_inline :nn {8} { \node [mynode] at (##ane, -#one) { \tiny \int_eval :n {(#one - 1) * 8 + ##1}}; } } \end {tikzpicture} \ExplSyntaxOff Output:
Floating betoken number (XXIII) and dimension (Xx)
The usage of floating point numbers is similar to that of integers: they all take their corresponding new, set, eval and compare functions. It is worth noticing that \fp_eval :north supports a series of scientific functions, which is demonstrated below.
\ExplSyntaxOn \fp_set :Nn \l_tmpa_fp {2.0} \par\fp_eval :n {sqrt(\l_tmpa_fp)} % 1.414213562373095 \par\fp_eval :n {sin(\l_tmpa_fp)} % 0.9092974268256817 \par \fp_eval :n {sin(\c_pi_fp)} % 0.0000000000000002384626433832795 \ExplSyntaxOff Information technology is worth noticing that 's floating indicate library is written in pure
, which means information technology differs from IEEE 754 floating betoken numbers fundamentally. Nonetheless, afterwards a serial of experiments, it is shown that
l3fp's arithmetic accuracy is near identical to IEEE 754 floating point. The discrapency is neglectable in everyday scenarios 7.
Floating points are similar to dimensions, except that dimensions are floating point numbers with a unit of measurement (unremarkably in pt). In , dimension variables are represented using IEEE 754 (single precision) floating point internally. Therefore, their processing speed is much faster than
l3fp. Dimension variables and floating betoken variables can be converted from one another using \dim_to_fp :due north and \fp_to_dim :n . It is possible to utilize dimension varialble directly in \fp_eval :north . In this instance, dimensions volition be converted into pt and lose their unit of measurement.
Drawing a rectangular number filigree in TikZ
\ExplSyntaxOn % set width and superlative of each cell \dim_new :N \l_w_dim \dim_set :Nn \l_w_dim {1.2cm} \dim_new :N \l_h_dim \dim_set :Nn \l_h_dim {0.5cm} \tikzset { mynode/.mode={ minimum~height=\l_h_dim, minimum~width=\l_w_dim, draw, anchor=north~west } } \begin {tikzpicture} \int_step_inline :nn {6} { \int_step_inline :nn {8} { \node [mynode] at (\fp_eval :n {##1 * \l_w_dim } pt, -\fp_eval :n {#1 * \l_h_dim } pt) { \tiny \int_eval :due north {(#1 - one) * 8 + ##i}}; } } \finish {tikzpicture} \ExplSyntaxOff Output:
Drawing points on a circumvolve and connect them pairwise
\ExplSyntaxOn \begin {tikzpicture} % describe points on the circle \int_step_inline :nn {x} { \node[fill=black, circumvolve, inner~sep=0pt, outer~sep=0pt, minimum~width=1mm] (n#ane) at ( \fp_eval :n {cos(#one * 36 * \c_one_degree_fp)} cm, \fp_eval :due north {sin(#one * 36 * \c_one_degree_fp)} cm ) {}; } % connect points pairwise \int_step_inline :nn {ten} { \int_step_inline :nn {x} { \depict (n#1)--(n##1); } } \end {tikzpicture} \ExplSyntaxOff Output:
LaTeX3: Data Construction
Queue (X, 15)
Queues are essential in the implementation of many algorithms. Hence, provides its queue implementation:
l3seq.
\ExplSyntaxOn % create new queue \seq_new :Due north \l_my_seq % empty queue \seq_clear :N \l_my_seq % button right into queue \seq_put_right :Nn \l_my_seq {howdy} \seq_put_right :Nn \l_my_seq {world} % bring together elements with '-' and output the result \seq_use :Nn \l_my_seq {-} % hello-world % get the length of queue \seq_count :N \l_my_seq % ii % pop the rightmost item and store it in \l_tmpa_tl \seq_pop_right :NN \l_my_seq \l_tmpa_tl % get the 1st item in the queue \seq_item :Nn \l_my_seq {i} % traverse items in queue % similar functions include \seq_map_inline: % and \seq_map_function: \seq_map_inline :Nn \l_my_seq { #i } \ExplSyntaxOff We call the l3seq container "queue" or "sequence" instead of "array" or "list". 1 of the reasons for this is that index access is read only: one tin can only access item with \seq_item :Nn , merely it is still impossible to alter an item based on index. Even so, if one wants to create a sequence of integer or floating signal numbers, it is possible to take advantage of l3intarray or l3fparray, which allows index-based consignment. As it will be discussed subsequently, they possess some other desirable qualities.
Educatee management system
\ExplSyntaxOn % a queue that stores student names \seq_new :N \l_student_seq \newcommand { \student }[1]{ #1% outputs student name % push student name to the right \seq_put_right :Nn \l_student_seq {#1} } \newcommand { \allstudent }{ % bring together elements in the queue with comma % and then output the outcome \seq_use :Nn \l_student_seq {,~} } \newcommand { \thestudent }[1]{ % outputs the #1-th element in the queue \seq_item :Nn \l_student_seq {#1} } \ExplSyntaxOff % John and Lisa and David and Emily \pupil {John} and \student {Lisa} and \pupil {David} and \pupil {Emily} % John, Lisa, David, Emily \par\allstudent % Emily and David and Lisa and John \par\thestudent {four} and \thestudent {3} and \thestudent {2} and \thestudent {1} Bracket matching
\ExplSyntaxOn \cs_set :Npn \my_paren_match :n #1 { % catechumen #1 into string \str_set :Nn \l_tmpa_str {#1} % articulate working queue \seq_clear :N \l_tmpa_seq % boolean variable to be set true if parentheses does non match \bool_set_false :Northward \l_tmpa_bool \str_map_inline :Nn \l_tmpa_str { % \str_case:nn is like the "switch" statement in C \str_case :nn {##one} { % ------ % for left brackets, simply button them into the queue {(} { \seq_put_right :Nn \l_tmpa_seq {(} } {[} { \seq_put_right :Nn \l_tmpa_seq {[} } % ------ % ------ % more than work needs to be done for right brackets {)} { % pop the rightmost chemical element and shop it in \l_tmpb_str \seq_pop_right :NN \l_tmpa_seq \l_tmpb_str % compare information technology with left round bracket % discover that the first argument is passed past value \str_if_eq :VnF \l_tmpb_str {(} { % this is executed only when equality does not hold % set "non match" to be truthful \bool_set_true :Due north \l_tmpa_bool % exits current loop \str_map_break : } } {]} { \seq_pop_right :NN \l_tmpa_seq \l_tmpb_str \str_if_eq :VnF \l_tmpb_str {[} { \bool_set_true :N \l_tmpa_bool \str_map_break : } } % ------ } } % run into if "non match" is true \bool_if :NTF \l_tmpa_bool {Not~Match} { % see if the working queue is empty \seq_if_empty :NTF \l_tmpa_seq {Match} {Not~Lucifer} } } \par\my_paren_match :northward {()()} % Lucifer \par\my_paren_match :n {([content()])()[]} % Match \par\my_paren_match :due north {([content())()[]} % Not Friction match \par\my_paren_match :n {([content()])()[} % Non Match \ExplSyntaxOff A very similar data construction is l3clist, which stands for "comma-separated list". Well-nigh functions provided past l3clist is same as l3seq, except that it provides a user-friendly constructor that allows one to initialize a sequence with comma-separated content. An example is given below.
\ExplSyntaxOn \clist_new :N \l_my_clist \clist_set :Nn \l_my_clist {This,is,my,list,ane,2,3} \clist_use :Nn \l_my_clist {-} %This-is-my-list-ane-2-three \ExplSyntaxOff Lexicon (XVII)
also provides primal-value access dictionary container:
l3prop. It is like to dict in Python or map in C++.
\ExplSyntaxOn % create new lexicon \prop_new :N \l_my_prop % clear dictionary \prop_clear :N \l_my_prop % add/update fundamental-value pair \prop_put :Nnn \l_my_prop {key} {val} % become value given fundamental \prop_item :Nn \l_my_prop {key} % val % get number of key-value pairs \prop_count :N \l_my_prop %i % traverse key-value pairs % similar functions include \prop_map_function: % and \prop_map_tokens: \prop_map_inline :Nn \l_my_prop { (#ane, #2) } % delete key-value pair \prop_remove :Nn \l_my_prop {cardinal} \ExplSyntaxOff Arabic numerals to English (0-99)
\ExplSyntaxOn \prop_new :N \l_english_prop \prop_set_from_keyval :Nn \l_english_prop { 0=zero, 1=one, 2=two, 3=three, four=iv, 5=five, six=six, 7=seven, eight=eight, ix=ix, 10=ten, xi=eleven, 12=twelve, 13=13, 15=15, 18=eighteen, 20=20, thirty=xxx, xl=xl, 50=fifty, lxxx=eighty } % actress scratch variable \tl_new :N \l_tmpc_tl \cs_set :Npn \my_arabic_to_eng :northward #one { \str_set :Nn \l_tmpa_str {#1} \prop_if_in :NVTF \l_english_prop \l_tmpa_str { % if the number is in the dictionary, output it directly % this works for most numbers under xx \exp_args :NNV \prop_item :Nn \l_english_prop \l_tmpa_str } { \int_compare :nNnTF {#1} < {20} { % deal with teens \exp_args :NNx \prop_item :Nn \l_english_prop { \int_eval :north {#1 - ten} } teen } { % deal with numbers between xx-99 % learn number in tens \int_set :Nn \l_tmpa_int { \int_div_truncate :nn {#1} {10} * 10 } % acquire number in ones \int_set :Nn \l_tmpb_int { #1 - \l_tmpa_int } % #one = \l_tmpa_int + \l_tmpb_int \tl_set :Nx \l_tmpa_tl { \int_use :N \l_tmpa_int } % outputs the "-ty" word \prop_if_in :NVTF \l_english_prop \l_tmpa_tl { % no need to construct: get from dict directly \exp_args :NNV \prop_item :Nn \l_english_prop \l_tmpa_tl } { % demand to construct the "-ty" discussion \tl_set :Nx \l_tmpc_tl { \tl_head :Due north \l_tmpa_tl } \exp_args :NNV \prop_item :Nn \l_english_prop \l_tmpc_tl ty } % no need to output second digit if it is zip \int_compare :nNnF { \l_tmpb_int } = {0} { % otherwise, prove 2nd digit \space \tl_set :Nx \l_tmpb_tl { \int_use :N \l_tmpb_int } \exp_args :NNV \prop_item :Nn \l_english_prop \l_tmpb_tl } } } } \par\my_arabic_to_eng :n {0} % zero \par\my_arabic_to_eng :n {18} % eighteen \par\my_arabic_to_eng :n {53} % l three \par\my_arabic_to_eng :n {85} % eighty 5 \ExplSyntaxOff A number of containers provide item-based access methods. For example,
\tl_item :Nn , \seq_item :Nn , \prop_item :Nn , etc. Different in most programming languages, where the complication of these methods are constant time (or in some cases, logarithmic time), these methods takes linear time in . That is to say, the larger the container is, the longer the boilerplate access time volition be.
Fundamentally, is a text-based macro language. There is no easy style for
scripts to admission a figurer's memory infinite directly. As a result, all containers are essentially synthetic with text and requires farther interpretation when use. This implies that most
containers accept extremely loftier time and memory consumption.
If one wants to store an assortment of integer or floating betoken number in , at that place are two types of high performance containers that allow abiding time access, namely
l3intarray and l3fparray. In this article, I discussed how to use l3intarray to speed up string reversal.
LaTeX3: Regular Expression (XXVIII)
Regular expression is a powerful tool for pattern matching in text documents. In , the
l3regex module provides limited support for standard regular expression syntax. These are some of the frequently used functions in l3regex:
-
\regex_new :N: creates new regular expression variable -
\regex_set :Nn: prepare the content of a regular expression variable - All of the following functions have either a raw regular expression or regular expression variable as the first argument. Raw regular expressions surrounded by braces requires compilation earlier use. The
\regex_set :Nnoffice will apply both compilation and storage. Therefore, for a regular exression used multiple times, saving information technology in a variable may save some time. -
\regex_match :nnTF: match a string based on the regular expression and executeT/Fcode based on the outcome -
\regex_count :nnN: count the number of matches and store the result in an integer variable -
\regex_extract_once :nnN: extract the beginning match in the cord and store it in a token listing variable -
\regex_extract_all :nnN: excerpt all matches in the string and store them in a queue -
\regex_split :nnN: divide the cord based on the regular expression and saved the result in a queue -
\regex_replace_once :nnN: replace the first match -
\regex_replace_all :nnN:supersede all matches
To allow interaction with , the syntax of
l3regex is slightly different from the standard. For more details, delight see documentation.
Cheque if a character is Chinese
\ExplSyntaxOn % create and compile regex \regex_new :N \l_chn_regex % the regular expression for Chinese characters \regex_set :Nn \l_chn_regex {[\x {3400}-\x {9FBF}]} \cs_set :Npn \my_is_chn :north #one { % store #1 as string \str_set :Nn \l_tmpa_str {#1} % clear outcome queue \seq_clear :N \l_tmpa_seq % traverse the string \str_map_inline :Nn \l_tmpa_str { % check if the string matches \l_chn_regex \regex_match :NnTF \l_chn_regex {##ane} { % if then, output Y \seq_put_right :Nn \l_tmpa_seq {Y} } { % otherwise, output Northward \seq_put_right :Nn \l_tmpa_seq {N} } } % show all contents in the queue, separated by white infinite \seq_use :Nn \l_tmpa_seq { \space } } % Y N Y N \par\my_is_chn :due north {中a文b} % N Northward N N Due north North Northward Y Y Y \par\my_is_chn :n {바탕체ヒラギノ細明體} \ExplSyntaxOff Substitute a command with some other
In the following example, all occurrence of \cmda is replaced by \cmdb . This example makes utilise of l3regex's special syntax.
\newcommand { \cmda }[1]{(#one)} \newcommand { \cmdb }[ane]{[#one]} \ExplSyntaxOn \tl_set :Nn \l_tmpa_tl { \cmda {X}~\cmdb {Y}} \par\tl_use :North \l_tmpa_tl % (10) [Y] % \c will capture control names \regex_replace_all :nnN { \c {cmda}} { \c {cmdb}} \l_tmpa_tl \par \tl_use :N \l_tmpa_tl % [X] [Y] \ExplSyntaxOff Generate TikZ picture based on a template
\tikzset { mynode/.fashion={ outer sep=0pt } } \ExplSyntaxOn % this is the template of each node % which we will make full with regular expressions \tl_new :Due north \l_template_tl \tl_set :Nn \l_template_tl { \node [mynode,@1] (@2) at (@3) {@4}; } % counts the total number of nodes \int_new :N \l_node_counter_int \int_gset :Nn \l_node_counter_int {0} % #1: style % #ii: angle % #3: content \cs_set :Npn \my_draw_node :nnn #ane#2#3 { % ready our working variable \tl_set_eq :NN \l_tmpa_tl \l_template_tl % fill fashion \regex_replace_once :nnN {@i} {#1} \l_tmpa_tl % increment counter \int_gincr :N \l_node_counter_int % store the name of new node in \l_tmpb_tl % node name is generated with \int_to_alph:due north \tl_set :Nx \l_tmpb_tl { \int_to_alph :n { \l_node_counter_int }} % fill node proper name % use \u to supervene upon with the content of a token list \regex_replace_once :nnN {@2} { \u {l_tmpb_tl}} \l_tmpa_tl % calculate the position of the node based on angle \tl_set :Nx \l_tmpb_tl { \fp_eval :n {three * cos(#2 * \c_one_degree_fp)}, \fp_eval :north {3 * sin(#2 * \c_one_degree_fp)} } % fill position \regex_replace_once :nnN {@3} { \u {l_tmpb_tl}} \l_tmpa_tl % fill content \regex_replace_once :nnN {@iv} {#3} \l_tmpa_tl % output result \tl_use :N \l_tmpa_tl } \begin {tikzpicture} \my_draw_node :nnn {circle,draw}{200}{Fifty} \my_draw_node :nnn {describe}{160}{A} \my_draw_node :nnn {circle,draw}{120}{T} \my_draw_node :nnn {draw}{lxxx}{E} \my_draw_node :nnn {circle,draw}{xl}{X} \my_draw_node :nnn {draw}{0}{3} \draw (a)--(b)--(c)--(d)--(eastward)--(f)--(a); \finish {tikzpicture} \ExplSyntaxOff Output:
LaTeX3: File I/O (Nineteen)
In , the APIs of file operations are standardized.
File reading:
-
\ior_new :Due north: create new I/O read variable -
\ior_open :Nn: open file for reading -
\ior_close :North: close file -
\ior_get :NN: read one line or a consummate grouping as token list -
\ior_str_get :NN: read one line equally string -
\ior_map_inline :Nn: traverse file as token list -
\ior_str_map_inline :Nn: traverse file equally string -
\ior_if_eof_p :N: bank check if the tail of a file is reached
File writing:
-
\iow_new :Northward: create new I/O write variable -
\iow_open :Nn: open up file for writing -
\iow_close :N: shut file -
\iow_now :Nn: immediately write content into the file, followed by a line break -
\iow_newline :: line pause function-this function must be expanded in order to take issue (east.g.\iow_now :Nx \l_tmpa_iow { \iow_newline : }; if the 2d argument has typenorth, goose egg volition happen)
Writing to a file
\ExplSyntaxOn \iow_open :Nn \g_tmpa_iow {testfile1.txt} \iow_now :Nx \g_tmpa_iow {hello\iow_newline : world} \iow_close :N \g_tmpa_iow \ExplSyntaxOff The content of testfile1.txt:
Reading and parsing comma-separated file
In the following example, we store a series of decimal numbers in a comma-separated file. So, we read the file and summate the sum of all numbers.
\ExplSyntaxOn % write numbers to testfile2.txt \iow_open :Nn \g_tmpa_iow {testfile2.txt} \iow_now :Nx \g_tmpa_iow {1.2,2.6,3.7,4.nine,5.0,6.five,7.4,8.2,9.4,x.eight} \iow_close :N \g_tmpa_iow % open up file for reading \ior_open :Nn \g_tmpa_ior {testfile2.txt} % become the first line \ior_str_get :NN \g_tmpa_ior \l_tmpa_str % create office variant \cs_generate_variant :Nn \regex_split :nnN {nVN} % divide the line into a queue with regular expression \regex_split :nVN {,} \l_tmpa_str \l_tmpa_seq % initialize the sum variable \fp_set :Nn \l_tmpa_fp {0.0} % traverse the queue \seq_map_inline :Nn \l_tmpa_seq { % sum the numbers \fp_add :Nn \l_tmpa_fp {#1} } % show result in math mode $ \seq _use:Nn \l _tmpa_seq { + } = \fp _use:N \50 _tmpa_fp $ % close file \ior_close :N \g_tmpa_ior \ExplSyntaxOff Output:
1.2+2.6+3.7+iv.9+5.0+6.5+7.4+viii.2+9.four+10.eight=59.7 Memo
Useful techniques:
Because the number of modules is huge, it is very difficult to cover most of them in a express amount of time. Here, I listing another libraries that are worth looking at:
-
l3coffins(XXX),l3box(XXIX): allows one to gauge the width/elevation of objects -
l3intarray(XXII),l3fparray(XXIV): high operation numeric arrays -
l3sort: sotring queues/token lists -
l3msg: generating exception messages
Stop Note
In this article, I try to breifly introduce the naming convention, the usage of variables and functions and some ordinarily used modules of . I promise that this organisation enables readers to understand the basics of
, which allows them to write simple
programs speedily.
There is no doubt that many documents can benefit from the programming capabilities of . It is really distressing that existing tutorials on
is rare, which significantly limits the evolution of this linguistic communication. Hopefully, this article can aid more people get familar with this powerful tool.
Source: https://www.alanshawn.com/latex3-tutorial/
0 Response to "Illegal Parameter Number in Definition of Test. N L.73 End{itemize}"
Post a Comment