Is there any difference between defining a variable using \def
and using \define
, when used without a number inside square brackets, e.g. \def\somecommand{\percent}
and \define\somecommand{\percent}
? Can I always use \define
in places where \def
can be used?
1 Answer
For reference: There are two definitions of \define
: The first one in
syst-aux.mkiv shows the behavior Egreg mentioned in his comment: if
the macro is already defined, it leaves it as it is. (A companion,
\redefine
allows you to overwrite the current definition of macro
regardless of its being in use.) Ironically, this preliminary
definition is overwritten without note as soon as the format loads
core-sys.mkiv (while \redefine
stays around forever).
The actual definition
of the \define
macro as provided by the user interface does not only
check for previously defined control sequences of the same name, but
also serves as some kind of short notation for mandatory arguments.
It has the scheme
\define [<digit>] <macro> {<definition>}
where the first argument, a digit, specifies the number of arguments the new macro is going to accept. Obviously this can result in shorter definitions. For comparison, the selector
\def\sevenofnine#1#2#3#4#5#6#7#8#9{#7}
\starttext
\sevenofnine abcdefghi\par
\stoptext
requires some less typing with the \define
macro:
\define[9]\sevenofnine{#7}
Thus these definitions may result in more readable code -- which is always a good thing when writing TEX.
Unfortunately the \define
wrapper takes away a good deal of the
expressiveness of plain \def
’s. In Context, you will have noticed,
macros taking optional arguments are commonplace with respect to the
user inteface. For example you simply can’t replace the second
\def
inition in below snippet with an equivalent expression using
\define
:
\unprotect
\def\myfoo{\dosingleempty\do_my_foo}
\def\do_my_foo[#1]#2{%
\iffirstargument{\bf\WORD#1}\fi
#2\par%
}
\protect
\starttext
\myfoo{bar}
\myfoo[foo]{bar}
\stoptext
That’s because with \define
you can’t specify the argument
delimiters (here: brackets) necessary for optional arguments, so
basically your macros are limited to taking mandatory (braced)
arguments only. For the same reason there is no way to define
cheap \{start|stop}something
environments either:
\let\stopfoo\relax
\def\startfoo#1\stopfoo{\bgroup\bold#1\egroup}
%%% ^^^^^^^^ not possible
\starttext
\startfoo
bar
\stopfoo
\stoptext
(The user interface for this is \definestartstop
(cf.
core-sys.mkiv), anyways.)
Finally, nowadays the most important drawback of \define
is that it
does not allow for mkvi-style arguments. There is simply no way to
refer to a parameter by its name if you can’t assign it one in the
first place.
% macros=mkvi
\unprotect
\def\foo{\dosingleempty\do_foo}
\def\do_foo[#optional]#mandatory{%
\bgroup\sansbold#optional\space\egroup
#mandatory\par%
}
\protect
\starttext
\foo{bar}
\foo[foo]{bar}
\stoptext
So if you want to do some serious macro writing, you will soon learn to
avoid \define
, while it is safe for less complex tasks.
-
Thank you for this helpful answer. Point of clarification: when you say "mkiv-style arguments", does that mean named arguments, like
#optional
in your example? Do you have a reference for where I can read more about those?– LarsHNov 13, 2013 at 15:27 -
2@LarsH Yes, MkVI (not MkIV!) macros are the ones with (optional) parameter names. I’m not sure there exists any user-level documentation besides the source: the preprocessor code can be found in
luat-mac.lua
(for Context) andluatex-preprocessor.lua
for Luatex-Plain. Hth. Nov 13, 2013 at 16:24 -
-
2I don't know if this was the case at the time of writing this answer but today macros defined using
\define
are e-TeX protected. To have it expandable one has to use\defineexpandable
(or plain\def
). Sep 27, 2016 at 20:52
\define\xyz{...}
, when\xyz
is already defined issues a warning, but performs the definition anyway. Of course\def
doesn't issue any warning.