%LaTex implementation:
%\def\@ifundefined#1{%
% \expandafter\ifx\csname#1\endcsname\relax
% \expandafter\@firstoftwo
% \else
% \expandafter\@secondoftwo
% \fi}
\parskip=10pt \def\AAAA{1}
\long\def\firstoftwo#1#2{#1}
\long\def\secondoftwo#1#2{#2}
\def\ifundefined#1{%
\expandafter\ifx\csname#1\endcsname\relax
\expandafter\firstoftwo
\else
\expandafter\secondoftwo
\fi}
\ifundefined{AAAA}{AAAA is undefined}{AAAA is defined} \par
\ifundefined{BBBB}{BBBB is undefined}{BBBB is defined}
\bye
Running gives
AAAA is defined
BBBB is undefined
> Hi - for a citation macro I would like to implement \ifundefined under
> Plain TeX
> with the standard TeX engine.
See package ltxcmds.sty, it can also be used with plain TeX
or even iniTeX. It implements
\ltx@IfUndefined and \ltx@ifundefined
in different ways, depending on the TeX engine
(e.g. eTeX provides \ifcsname).
> I tried to parrot LaTeX's @ifundefined
> as shown
> below, and seems to work. Any foreseeable problems with this
> particular code?
> Thanks.
>
> %LaTex implementation:
> %\def\@ifundefined#1{%
> % \expandafter\ifx\csname#1\endcsname\relax
> % \expandafter\@firstoftwo
> % \else
> % \expandafter\@secondoftwo
> % \fi}
Undefined commands become the meaning \relax.
This is a side effect of \csname.
That's undefined in the sence of \@ifundefined, but
not using
\ifx\mymacro\UNDEFINED
\message{undefined}%
\else
\message{defined}%
\fi
\@ifundefined{mymacro}{}{}
\ifx\mymacro\UNDEFINED
\message{undefined}%
\else
\message{defined}%
\fi
Is \mymacro is undefined in the first place,
then it's defined afterwards.
This can be fixed by using a group:
\def\@undefined@nonexpandable#1{%
\begingroup\expandafter\expandafter\expandafter\endgroup
expandafter\ifx\csname #1\endcsname\relax
\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo
\fi
}
But this version is not expandable.
If eTeX is available, then also an
expandable way can be provided,
see ltxcmds.
--
Heiko Oberdiek
Thanks for the advice. Actually I didnt see those "name pollution"
side effects so far. If I do more tests,
\ifundefined{AAAA}{AAAA is undefined}{AAAA is defined} \par
\ifundefined{BBBB}{BBBB is undefined}{BBBB is defined} \par
\ifundefined{BBBB}{BBBB is undefined}{BBBB is defined} \par
\ifundefined{relax}{relax is undefined}{relax is defined} \par
\ifundefined{ifundefined}{ifundefined is undefined}{ifundefined is
defined} \par
\ifundefined{AAAA}{AAAA is undefined}{AAAA is defined} \par
\ifundefined{BBBB}{BBBB is undefined}{BBBB is defined} \par
I get the expected answers. Well, with one exception: \relax is
considered undefined - bit of a mistery to me since it is a primitive
defined to do nothing.
Are there more stringent tests that point the need
for extra grouping?
> Hi - for a citation macro I would like to implement \ifundefined under Plain
> TeX with the standard TeX engine. I tried to parrot LaTeX's @ifundefined as
> shown below, and seems to work. Any foreseeable problems with this particular
> code? Thanks.
The problem is that making \csnames of things actually
defines the command as \relax, so you can't later perform
the test \ifx\foo\undefined. If you can run "etex" and
use \ifcsname then there is not that conflict.
Donald Arseneau as...@triumf.ca
That is a good warning. I'll check with \show\cs if there is
pollution,
and apply grouping to kill those names.
> Thanks for the advice. Actually I didnt see those "name pollution"
> side effects so far.
Because your \ifundefined (like LaTeX's \@ifundefined) doesn't
distinguish between undefined and \relax.
> Well, with one exception: \relax is considered undefined - bit of a
> mistery to me
Please reread Heiko's answer. You actually test whether the control
sequences are equal to \relax, not whether they are undefined, and
because you use \csname, you define them while testing. Traditionally
control sequences equal to \relax and undefined control sequences have
not been distinguished by LaTeX, but technically they are different.
--
Change “LookInSig” to “tcalveu” to answer by mail.
No this is because of the behaviour of \csname that you have understood:
one usually consider that a cs is not defined if it's meaning is
\undefined or \relax.
You can use another code (simpler by the way):
\def\testifnotdefined #1{\begingroup
\expandafter \endgroup \expandafter \ifx
\csname #1\endcsname\@undefined
\expandafter\@firstoftwo
\else \expandafter\@secondoftwo \fi
}
\testifnotdefined {something}{not defined }{ defined}
\testifnotdefined {something}{not defined }{ defined}
\testifnotdefined {relax}{not defined }{ defined}
This seems to work fine too:
\def\ifundefined#1{%
\begingroup \expandafter\ifx\csname#1\endcsname\relax
\expandafter\firstoftwo
\else
\expandafter\secondoftwo
\fi\endgroup}
since \show\BBBB gives =\undefined at the end of testing. Should I
make
\firstoftwo and \secondoftwo \global just in case?
That's one thing Don overlooked. Should have made \undefined
an untouchable primitive, distinguishable from \relax. Also
added \undef and \undefall primitives. Well he wanted to get back to
writing his books ...
No there is a problem: \endgroup is misplaced:
\expandafter\@firstoftwo \else ...\fi \endgroup
becomes: \@firstoftwo \endgroup {....} => \endgroup
But do you want to test for undefined only or for undefined or relax ?
\begingroup \expandafter \ifx \csname #1\endcsname\relax
\endgroup \expandafter\@firstoftwo
\else \endgroup \expandafter\@secondoftwo
\fi
> Are there more stringent tests that point the need
> for extra grouping?
\meaning delivers a sequence of catcode-12-character-tokens
denoting the phrase "undefined" in case the control-sequence/
active-character in question is undefined.
Crucial question: Can you trick \meaning into delivering
exactly a sequence of catcode-12-character-tokens
denoting the phrase "undefined" as leading sequence of its
result although the token in question is defined/has a
meaning?
If this is not possible, a check on the control-sequence-token
itself (not the sequence you'd pass to \csname..\endcsname)
might be feasible by testing whether the result of applying
\meaning to the control-sequence-token in question starts
with "undefined".
Ulrich
%%===============================================================
%%
%%---------------------------------------------------------------
%% \firstoftwo and \secondoftwo:
%%...............................................................
\long\def\firstoftwo#1#2{#1}
\long\def\secondoftwo#1#2{#2}
%%---------------------------------------------------------------
%% Check if control-sequence-token has been assigned a meaning:
%%...............................................................
\def\AtIfUndefined#1{%
\long\def\AtIfUndefined##1##2##3{%
\romannumeral\iffalse{\fi\expandafter\innerAtIfUndefined
\expandafter.\meaning##1#1}{}{0 ##3}{0 ##2}%
}%
\long\def\innerAtIfUndefined##1#1{%
\iffalse{\fi\expandafter\expandafter\expandafter\secondoftwo
\expandafter\expandafter\expandafter{\expandafter\expandafter
\expandafter{\expandafter\string\firstoftwo{}##1}\expandafter
\secondoftwo\string}\expandafter\firstoftwo\expandafter{%
\iffalse}\fi\expandafter\expandafter\expandafter\firstoftwo}%
{\expandafter\expandafter\expandafter\secondoftwo}%
\expandafter\secondoftwo\expandafter{\iffalse}\fi
}%
}%
% Somehow get the catcode-12-token-phrase "undefined" as argument
% of \AtIfUndefined:
\expandafter\AtIfUndefined\expandafter{\meaning\UndFINeD}%
%%===============================================================
\def\test{undefined}
\catcode`\Z=13
\AtIfUndefined{\UndFINeD}{undefined}{defined}
\AtIfUndefined{\relax}{undefined}{defined}
\AtIfUndefined{\TeX}{undefined}{defined}
\AtIfUndefined{\test}{undefined}{defined}
\AtIfUndefined{\par}{undefined}{defined}
\AtIfUndefined{\fi}{undefined}{defined}
\AtIfUndefined{\AtIfUndefined}{undefined}{defined}
\AtIfUndefined{\bgroup}{undefined}{defined}
\AtIfUndefined{\egroup}{undefined}{defined}
\AtIfUndefined{Z}{undefined}{defined}
\letZ=\relax
\AtIfUndefined{Z}{undefined}{defined}
\AtIfUndefined{\UndFINeD}{undefined}{defined}
\bye
Impressive... but: is there a link with typography ?
> Impressive... but: is there a link with typography ?
The OP did not ask about "a link with typography" but
about implementing \ifundefined under Plain TeX.
Many discussions on that matter took place already.
Thus I decided to take this discussion for a moot
point.
I seldom use TeX for accomplishing tasks related to
typography. It's a toy similar to a crossword puzzle
or a chessboard.
Ulrich
In my previous posting I overlooked that with \meaning you
don't need to take extra care for preventing brace-stripping
from arguments as no tokens of catcode1/2 will be involved.
I don't know what I was thinking but I assume that there is
still the possibility of optimization.
Ulrich
%%===============================================================
%% \firstoftwo and \secondoftwo:
%%...............................................................
\long\def\firstoftwo#1#2{#1}
\long\def\secondoftwo#1#2{#2}
%%---------------------------------------------------------------
%% Check if control-sequence-token has been assigned a meaning:
%%...............................................................
\def\AtIfUndefined#1{%
\long\def\AtIfUndefined##1##2##3{%
\romannumeral\iffalse{\fi\expandafter\innerAtIfUndefined
\meaning##1#1}{}{0 ##3}{0 ##2}%
}%
\long\def\innerAtIfUndefined##1#1{%
\iffalse{\fi\expandafter\secondoftwo\expandafter{\string##1}%
\expandafter\firstoftwo\expandafter{\iffalse}\fi\expandafter
\expandafter\expandafter\firstoftwo}{\expandafter\expandafter
\expandafter\secondoftwo}\expandafter\secondoftwo\expandafter
{\iffalse}\fi
}%
}%
% Somehow get the catcode-12-token-phrase "undefined" as argument
% of \AtIfUndefined:
\expandafter\AtIfUndefined\expandafter{\meaning\UndFINeD}%
%%===============================================================
\def\test{undefined}
\def\testb{{{braces}}}
\catcode`\Z=13
\AtIfUndefined{\UndFINeD}{undefined}{defined}
\AtIfUndefined{\relax}{undefined}{defined}
\AtIfUndefined{\TeX}{undefined}{defined}
\AtIfUndefined{\test}{undefined}{defined}
\AtIfUndefined{\par}{undefined}{defined}
\AtIfUndefined{\fi}{undefined}{defined}
\AtIfUndefined{\AtIfUndefined}{undefined}{defined}
\AtIfUndefined{\bgroup}{undefined}{defined}
\AtIfUndefined{\egroup}{undefined}{defined}
\AtIfUndefined{Z}{undefined}{defined}
\letZ=\relax
\AtIfUndefined{Z}{undefined}{defined}
\AtIfUndefined{\testb}{undefined}{defined}
> \meaning delivers a sequence of catcode-12-character-tokens..
> %% Check if control-sequence-token has been assigned a meaning:
I don't see the point. If you are testing a control sequence token
then just use \ifx. The problem is with copying LaTeX's \@ifundefined
where the cs name is given as a text argument; \csname \endcsname has
unfortunate properties (confusion between undefined and relax) and side
effects (assignment as \relax). These deficiences are addressed by
e-TeX with \ifcsname.
Donald Arseneau as...@triumf.ca
but the op didn't want to do anything so radical as to use something don
k does without. i've never understood this attitude, but there we are.
--
Robin Fairbairns, Cambridge
my address is @cl.cam.ac.uk, regardless of the header. sorry about that.
> Ulrich D i e z <eu_an...@web.de> writes:
>
> > \meaning delivers a sequence of catcode-12-character-tokens..
> > %% Check if control-sequence-token has been assigned a meaning:
>
> I don't see the point. If you are testing a control sequence token
> then just use \ifx.
You mean comparing the token in question to an undefined
control-sequence? Of course. As I experienced that some
people somehow managed to get \undefined defined, I usually
rely on some control-sequence with a rather obscure name,
e.g., \WEirDANdtHUshOPeFULlYUndeFIned, being undefined.
But in
news:296fcd15-cf09-4658...@22g2000prx.googlegroups.com
, Carlos wrote:
| That's one thing Don overlooked. Should have made \undefined
| an untouchable primitive, distinguishable from \relax. Also
| added \undef and \undefall primitives. Well he wanted to get back to
| writing his books ...
Due to the phrase "untouchable primitive" it seemed to me
that Carlos did not feel all too comfortable about relying on
a certain control-sequence being undefined.
Thus I presented the only way I know of expandably testing
whether a control-sequence is (un)defined in plain TeX without
the need of all the time relying on a certain token not being
defined.
Of course with that approach you instead need to rely on
other tokens not being redefined which might as well not
be the case with code written by people who define tokens
like "\undefined".
> \csname \endcsname has unfortunate properties
The problem is that \csname..\endcsname not only forms
a control-sequence-token but also makes that control-
sequence-token equal to \relax in the current scope in case
that control-sequence-token is not defined yet in the current
scope. (Seems that even if the value of the integer-parameter
\globaldefs is positive, the effect is restricted to the current
scope.)
This effect affects the result of testing. If you don't want
to use eTeX extensions but plain TeX while facing the need
of first "constructing" the control-sequence-token from a
sequence of characters, you need to choose whether to
cancel that effect by grouping (which implies that the test
won't be expandable any more) or whether actually rather
comparing the newly constructed control-sequence-token to
(the result of something that delivers a "frozen") \relax than
checking whether the control-sequence-token in question is
defined at all.
Sincerely
Ulrich
> Donald Arseneau wrote:
>
> > Ulrich D i e z <eu_an...@web.de> writes:
> >
> > > \meaning delivers a sequence of catcode-12-character-tokens..
> > > %% Check if control-sequence-token has been assigned a meaning:
> >
> > I don't see the point. If you are testing a control sequence token
> > then just use \ifx.
>
> You mean [...]
Reconsidering the facts I come to the conclusion that
once more actually the point is that I was carried away
in a weird fashion when scenting the opportunity of
showing-off.
I ask the gentle reader's forgiveness.
Sincerely
Ulrich
> Reconsidering the facts I come to the conclusion that
> once more actually the point is that I was carried away
Don't worry, there's no accusation of grandstanding. Just
normal topic-drift.
Donald Arseneau as...@triumf.ca