6

Consider the following macro definitions:

\def\mymacro#1{\mymacroii#1\nil}
\def\mymacroii#1#2\nil{%
  \ifx\\#1\\%
    empty%
  \else
    #1%
  \fi
}%
\mymacro{foo}% -> f
\mymacro{}
\bye

This is supposed to extract the first character of the parameter to \mymacro. This works, but only if the argument is not empty.

How must I change my macros, so that the call \mymacro{} works as expected, i.e. outputs "empty"? Note, that is is only a simplified version. In reality I have several checks in \mymacroii for the first character, if it is a number, an opening brace, and so on.

This question is for sure related to Why does TeX remove braces around delimited arguments?, but I couldn't apply those informations to my case.

4
  • Have you looked at the various token tests in expl3 (we have tests for opening brace, ... plus a very robust 'first token' function)?
    – Joseph Wright
    Jan 10, 2014 at 9:51
  • @JosephWright No, I haven't. This code is supposed to be used in my pst-optexp package, which doesn't use expl3. I don't want to add that dependencies for now, especially because I haven't worked with it at all.
    – Christoph
    Jan 10, 2014 at 9:53
  • 1
    I meant 'you could see how we've tackled this and use the same ideas': ther has been lots of testing of a number of approaches to these 'low level' problems.
    – Joseph Wright
    Jan 10, 2014 at 9:54
  • @JosephWright Thanks for the suggestion. I started from some ideas in the pstricks package. I had a look at the expl3 files, but couldn't get a good starting point. Where could I start for investigating on these specific tests?
    – Christoph
    Jan 10, 2014 at 10:30

2 Answers 2

6
\def\mymacro#1{\mymacroii#1{empty}\nil}
\def\mymacroii#1#2\nil{%
    #1%
}%

\mymacro{foo}% -> f

\mymacro{}
\bye

In your version, in the empty case, the inner call is

\mymacroii\nil

so #1 is \nil and then it starts looking for the next \nil (which isn't there) to make #2 and things go wrong.

4
  • Thanks. Unfortunately, my example was too minimal. In reality I have several different checks for the first argument in \mymacroii, it #1 is a number, a (, a < etc. I added this information to my question.
    – Christoph
    Jan 10, 2014 at 9:51
  • @Christoph Can't you just do your tests sequentially?
    – Joseph Wright
    Jan 10, 2014 at 9:52
  • @Christoph well you can add those to mine, the point is structuring that way means that #1 in your actual macro is never empty so you can write the tests knowing there is something there. Jan 10, 2014 at 9:53
  • @DavidCarlisle Thanks, it seems to work now. I'll test this solution in my package, before accepting the answer and closing the question.
    – Christoph
    Jan 10, 2014 at 10:28
3

Just check for emptyness first.

\long\def\firstoftwo#1#2{#1}
\long\def\secondoftwo#1#2{#2}
\def\mymacro#1{%
  \ifx\\#1\\%
    \expandafter\firstoftwo
  \else
    \expandafter\secondoftwo
  \fi
  {empty}%
  {\mymacroii#1\nil}%
}
\def\mymacroii#1#2\nil{#1}

Just to get the flavor with LaTeX3, here's a version that allows you to define a function that examines the first token of the argument provided it was not empty in the first place (in this case it would output empty). It works also in expanded definitions, as shown below.

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\mymacro}{ m }
 {
  \tl_if_empty:nTF { #1 }
   { empty }
   { \christoph_examine_first:f { \tl_head:n { #1 } } }
 }
\cs_new:Npn \christoph_examine_first:n #1
 {
  Whatever~you~want~with~#1~which~is~one~token
 }
\cs_generate_variant:Nn \christoph_examine_first:n { f }
\ExplSyntaxOff
\begin{document}

\mymacro{foo}

\mymacro{}

\edef\x{\mymacro{foo}\mymacro{}}\x

\end{document}
1
  • Thanks for your solution. I used David's answer, which fits better to the rest of my code.
    – Christoph
    Jan 11, 2014 at 13:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .