Интерфейс LaTeX3 для функций

Интерфейс LaTeX3 для функций

Недавно я разместил вопрос о написании макроса на простом TeX, который будет изменять элементы в указанном пользователем списке. Я небрежно упомянул о своей нелюбви к интерфейсу TeX, поэтому кто-то перевел меня на LaTeX3, который, как и обещает руководство, должен быть больше похож на современный язык программирования. Я только начинаю программировать на TeX, поэтому мне пришлось нелегко, пытаясь понять руководство. Я предполагаю, что это потому, что руководство было написано для опытных пользователей TeX; однако, похоже, что для людей, только начинающих работать с LaTeX3/TeX, нет альтернативы, поэтому у меня нет выбора, кроме как работать с тем, что у меня есть. Вот почему я публикую это. Руководство запутанное, и я хотел бы прояснить часть этой путаницы, задав вам несколько простых вопросов о синтаксисе.

Я должен упомянуть, что человек, который рассказал мне о LaTeX3, также дал мне решение для моего исходного поста с использованием его интерфейса. Я смог использовать это решение в сочетании с руководством, чтобы начать разбираться в некоторых основных фактах о синтаксисе LaTeX3. Я собираюсь рассказать о том, что мне удалось выяснить, но честно предупреждаю, что часть этого основана на моих собственных выводах, сделанных с помощью примера, предоставленного пользователем stackexchange, а не на явных инструкциях в руководстве, так что ждите ошибок. Я хотел бы, чтобы вы знали, я не запутываю ситуацию, когда иногда использую собственную терминологию. Просто сложно говорить о предмете, который вы не полностью понимаете, структурированным образом.

Также я пишу это как отдельный пост, а не комментарий, из-за его длины. Заранее спасибо.

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

Определения функций.

Что мне удалось выяснить на данный момент:

Новая функция определяется, среди прочего, с помощью следующего кода:

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

Это \cs_new_<restrictions>команда LaTeX, Npn сообщает «анализатору» интерфейса, что ему следует ожидать после части \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>}) друг от друга с помощью «мета-сигнатуры».Нпн.

Теперь, если я хочу избавиться от #, я могу использовать следующую общую команду

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

В файле есть и другие команды.l3basicsбиблиотека для создания функций, но их общая структура, по сути, та же самая. Единственное отличие в их функциональности. Так, например, использование \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. Однако, чтобы оценить всю мощь этой свободы, вам необходимо ознакомиться с главой 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>:Npnand :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>}

Связанный контент