Er der nogen forskel mellem at definere en variabel ved hjælp af \def
og bruge \define
, når det bruges uden et tal inden for firkantede parenteser, f.eks \def\somecommand{\percent}
og \define\somecommand{\percent}
? Kan jeg altid bruge \define
på steder, hvor \def
kan bruges?
Kommentarer
- Fra hvad jeg ser, udsender
\define\xyz{...}
, når\xyz
allerede er defineret, en advarsel, men udfører definitionen alligevel.\def
giver selvfølgelig ikke ' nogen advarsel.
Svar
Til reference: Der er to definitioner af \define
: Den første i syst-aux.mkiv viser den adfærd, Egreg nævnte i sin kommentar: hvis makroen allerede er defineret, efterlader den den, som den er. (En ledsager, \redefine
giver dig mulighed for at overskrive den aktuelle definition af makro uanset om den er i brug.) Ironisk nok overskrives denne foreløbige definition uden note, så snart formatet indlæses core-sys.mkiv (mens \redefine
forbliver for evigt).
Den definition af \define
makroen som leveret af brugergrænsefladen kontrollerer ikke kun for tidligere definerede kontrolsekvenser med samme navn, men fungerer også som en slags kort notation for obligatoriske argumenter. Det har skemaet
\define [<digit>] <macro> {<definition>}
hvor det første argument, et ciffer, angiver antallet af argumenter, som den nye makro vil acceptere. Dette kan naturligvis resultere i kortere definitioner. Til sammenligning kræver vælgeren
\def\sevenofnine#1#2#3#4#5#6#7#8#9{#7} \starttext \sevenofnine abcdefghi\par \stoptext
mindre skrivning med \define
makroen:
\define[9]\sevenofnine{#7}
Disse definitioner kan således resultere i en mere læselig kode – hvilket altid er en god ting, når du skriver TEX.
Desværre er \define
indpakning fjerner en hel del af udtryksevnen for almindelige \def
. I kontekst har du bemærket, at makroer, der tager valgfri argumenter er almindelige med hensyn til brugerens grænseflade. For eksempel kan du simpelthen ikke erstatte den anden \def
inition i nedenstående uddrag med et tilsvarende udtryk ved hjælp af \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
Det skyldes, at du med \define
ikke kan angive argumentafgrænsere (her: parenteser), der er nødvendige for valgfri argumenter, så dybest set er dine makroer begrænset til kun at tage obligatoriske (afstivet) argumenter. Af samme grund er der heller ikke nogen måde at definere billige \{start|stop}something
miljøer på:
\let\stopfoo\relax \def\startfoo#1\stopfoo{\bgroup\bold#1\egroup} %%% ^^^^^^^^ not possible \starttext \startfoo bar \stopfoo \stoptext
(Brugergrænsefladen til dette er \definestartstop
(jf. core-sys.mkiv ), alligevel.)
Endelig i dag er den vigtigste ulempe ved \define
er, at det ikke tillader argumenter for mkvi -stil. Der er simpelthen ingen måde at henvise til en parameter med dens navn hvis du ikke kan tildele den en i første omgang.
% 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
Så hvis du vil lave seriøs makroskrivning, lærer du snart at undgå \define
, mens det er sikkert for mindre komplekse opgaver.
#optional
i dit eksempel? Har du en reference til, hvor jeg kan læse mere om dem?luat-mac.lua
(til kontekst) ogluatex-preprocessor.lua
til Luatex-Plain. Hth.\define
e-TeX beskyttet. For at få det udvideligt skal man bruge\defineexpandable
(eller almindeligt\def
).