Из общих языков программирования я привык вызывать функции следующим образом:
myfunction(argument1, argument2, ..., argumentn)
Похоже, что латекс требует такой синтаксис.
\mycommand{argument1}{argument2}...{argumentn}
использовать команды. Могу ли я вызывать команды, используя обычный синтаксис функций (вместо того, чтобы писать скобки для каждого аргумента)? Я хочу иметь возможность сделать это:
\mycommand{argument1, argument2, ..., argumentn}
решение1
Другие ответы касались того, как можно разделить запятыми, но, возможно, более широкое объяснение также будет полезным. Важно начать с того факта, что хотя LaTeX можно программировать в целом, это система подготовки документов для набора. Дизайн базового языка (TeX) также отражает ту же цель, и LaTeX в значительной степени использует те же соглашения, что и сам TeX.
В плане передачи аргументов TeX имеет дело с «сбалансированным текстом», который представляет собой некоторый произвольный материал (обычно) начинающийся с {
и заканчивающийся на }
. Символы, используемые для разграничения «сбалансированного текста», можно изменить, но не тот факт, что нам нужны эти два и что они различны. Это означает, что мы должны передавать аргументы в форме
\foo{balanced text 1}{balanced text 2}
и т. д.TeX допускает более сложный «разграниченный» тип аргумента, поэтому мы можем настроить (как Дэвид как сделано) для разделения материала запятыми
\def\foo(#1,#2){Stuff with #1 and #2}
\foo(abc,def) => #1 = abc, #2 = def
но это должно быть определено на уровне программирования: мы не можем просто «переключить основной синтаксис». Более того, простое определение, которое я только что использовалтребуетзапятая во входных данных: если вы моделируете на других общих языках, вы, вероятно, ожидаете, что аргументы будут необязательными. Можно использовать более сложное программирование для разделения на переменное количество запятых, но это всегда будет слоемнаверхуядра.
Один ключевой момент, который следует иметь в виду, заключается в том, что TeX не имеет строковых данных или разделения функций/переменных: у нас есть только «токены». Важно, что это означает, что мы вполне могли бы ожидать, что запятая будет использоваться где угодно, и поэтому должны «защищать» запятые, если мы используем синтаксис \foo(abc,efg):
\foo({abc,def},ghi) => #1 = abc,def; #2 = ghi
что (для меня) не яснее, чем
\baz{abc,def}{ghi}
Также стоит отметить, что использование ( ... )
также несет в себе некоторые проблемы: они не могут появляться в аргументах, не вызывая проблем или не требуя более сложной настройки кода (см. xparse
).
решение2
Способ expl3
(не использующий \SplitList
напрямую xparse) путем определения команды и команды обработки, которая что-то делает с элементами списка аргументов, но эта команда обработки по сути выполняет одну и ту же операцию над отдельными элементами списка.
Примечание: в случае большого количества аргументов, имеющих разное значение, key-value
более эффективным или, по крайней мере, менее подверженным ошибкам является тот или иной подход.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\newcommand{\foocmd}[1]{%
\seq_set_from_clist:Nn \l_tmpa_seq {#1}
\seq_map_inline:Nn \l_tmpa_seq {%
\fooprocessorcmd{##1}%
}
}
\ExplSyntaxOn
\newcommand{\fooprocessorcmd}[1]{\fbox{#1}}
\begin{document}
\foocmd{r,o,f,y,b,i,v}
\end{document}
решение3
Не всегда хорошая идея навязывать идиомы из одного языка в другой, но, например,
\documentclass{article}
\def\zz#1{\zzz#1\relax}
\def\zzz#1,#2,#3,#4\relax{\fbox{#1} \fbox{#2} \fbox{#3} \fbox{#4}}
\begin{document}
\zz{a,b,c,d}
\end{document}
Обратите внимание, что в отличие от обработки списка, разделенного запятыми (как, например)
\usepackage{array,color,longtable,booktabs}
Определенный выше метод \zz(z)
имеет фиксированное количество аргументов, к которым можно получить доступ, #1
но #4
с использованием синтаксиса запятой, а не {}
.
Также предполагается, что четыре аргумента не включают ,
или, \relax
если они необходимы, их необходимо защитить, {}
поэтому\zz{{1,2},{3,4},{5,6},{7,8}}
решение4
Вот очень простой listofitems
подход.
\documentclass{article}
\usepackage{listofitems}
\newcommand\mycommand[1]{%
\readlist*\myargs{#1}%
The \myargslen{} arguments are \showitems\myargs.
The 4th argument is ``\myargs[4].''
}
\begin{document}
\mycommand{this, is, a, big, test}
\mycommand{What, would, you do, for a, Klondike, bar?}
\end{document}