I seem to be stuck and for now am trying my luck through trial and error to find the right way to do this.

Here is a general idea:

% I DECLARE NEW MACROS WITH NAMES AS DEFFINITION. AND ASIGN LETTERS TO PEOPLE SINCE NUMBERS ARE FORBIDEN IN MACRO'S NAMES.
\newcommand{\AuthorNameA}{John}
\newcommand{\AuthorSurnameA}{Doe}
\newcommand{\AuthorNameB}{Jane}
\newcommand{\AuthorSurnameB}{Doe}
\newcommand{\AuthorNumber}{3}

% DECLARE NEW COUNTER
\newcounter{loopTitleCoverAuthor}

% START WITH LOOP
\forloop{loopTitleCoverAuthor}{1}{

   %COMPARE COUNTER WITH DEFINITION OF MACRO SET PREVIOUSLY
   \value{loopTitleCoverAuthor} < \value{bfThesisAuthorNumber}
}{
% IF CONDITION IS TRUE CHECK IF MACRO WITH PARTICULLAR ENDING IS DEFINED AND IF IT IS, PRINT NAME AND SURNAME
\ifdefined\expandafter\AuthorName\Alph{loopTitleCoverAuthor}
   \expandafter\AuthorName\Alph{loopTitleCoverAuthor} \textsc{\expandafter\AuthorSurname\Alph{loopTitleCoverAuthor}}\\
\fi
}

a) Not surprisingly that didn't work. The first issue I got was comparing the counter to a macro value. So to continue and to see what else might be wrong I changed condition part to:

\value{loopTitleCoverAuthor} < 3 %\value{bfThesisAuthorNumber}

b) Then I had a problem with \ifdefined check so I commented that out too and name and surname macros are always called.

c) Lastly I had a problem with \expandafter (I think). I now get output, but not as it should be. It omits \AuthorName and \AuthorSurname and prints only \Alph of the counter step.

I would expect to see:

John Doe
Jane Doe

I get:

AA
BB

So, those are my questions:

  1. Is it possible to use a value of macro in the condition of \forloop(a)?

  2. How should I reformat \ifdefined to check properly if macro is defined in each loop (\AuthorNameA in first loop, \AuthorNameB in second ...) (b)? I also tried with \csname, multiple \expandafter, \expandafter before \ifdefined, ... Nothing described here: https://www.tug.org/TUGboat/tb09-1/tb20bechtolsheim.pdf seems to work (or more likely I'm doing something obviously wrong and can't see it).

  3. What should I change so that \AuthorNameA gets expanded (c)?

  4. Is there a generally better way to do this? Declare "controls and variables" in one file and then \input that file and use values of those macros in loops to display and control output?

  • What is the bfThesisAuthorNumber I don't see any definition. – MaestroGlanz Apr 22 '16 at 17:29
  • What I learned just the other day, is that if you use \ifdefined\csname... you always get true. If the function in \csname is undefined, it returns \relax. That means, it should be \expandafter\ifx\csname someStuff\endcsname\relax (You compare the macro with \relax`). I don't get the question exactly, so I write this as a comment first. – MaestroGlanz Apr 22 '16 at 17:32
  • @MaestroGlanz You can do \ifcsname...\endcsname that returns true if the control sequence that would be obtained by \csname...\endcsname has a meaning and false otherwise, but without making it equivalent to \relax. – egreg Apr 22 '16 at 17:59
  • @MaestroGlanz It's a typo. My apologies. I shortened my code for easier read but missed that one. It should be just \AuthorNumber. Thank you for your help and time! – Nejc Draganjec Apr 22 '16 at 19:47
up vote 4 down vote accepted

The test \value{A} < \value{B} works for me.

I've used \@ifundefined{csname}{true}{false} where csname is the command name to be tested without the escape character \.

The most important thing here is constructing the various command names, with \csname foo\Alph{...}\endcsname.

\documentclass{article}


\usepackage{forloop}

\newcommand{\AuthorNameA}{John}
\newcommand{\AuthorSurnameA}{Doe}
\newcommand{\AuthorNameB}{Jane}
\newcommand{\AuthorSurnameB}{Doe}
\newcommand{\AuthorNumber}{5}

% DECLARE NEW COUNTER
\newcounter{loopTitleCoverAuthor}

\newcounter{bfThesisAuthorNumber}
\setcounter{bfThesisAuthorNumber}{\AuthorNumber}


\begin{document}
% START WITH LOOP
\makeatletter 
\forloop{loopTitleCoverAuthor}{1}{%
  % COMPARE COUNTER WITH DEFINITION OF MACRO SET PREVIOUSLY
  \value{loopTitleCoverAuthor} < \value{bfThesisAuthorNumber} % End condition
}{
  \@ifundefined{AuthorName\Alph{loopTitleCoverAuthor}}{%
    Booooooooooooo: Author \Alph{loopTitleCoverAuthor} is not defined!

  }{
    Hooray:  Author \Alph{loopTitleCoverAuthor} exists and is \csname AuthorName\Alph{loopTitleCoverAuthor}\endcsname 

    \csname AuthorName\Alph{loopTitleCoverAuthor}\endcsname\ \textsc{\csname AuthorSurname\Alph{loopTitleCoverAuthor}\endcsname}

  }
}
\makeatother    
\end{document}

enter image description here

  • 1
    Thank you very much! I managed to merge your example with my production code and now it works. Especially \setcounter{bfThesisAuthorNumber}{\AuthorNumber}, ifundefined and csname parts were very helpfull since I wasn't sure what syntax should be. And then, sure enough, I wrote it all wrong and nothing worked. All sorted now, so thanks again! – Nejc Draganjec Apr 22 '16 at 19:52
  • @NejcDraganjec: You're welcome! Happy TeXing! – Christian Hupfer Apr 22 '16 at 19:53

There are a few problems with your code.

  1. The code

    \ifdefined\expandafter\AuthorName\Alph{loopTitleCoverAuthor}
    

    tests whether \expandafter is defined.

  2. However the code

    \expandafter\ifdefined\expandafter\AuthorName\Alph{loopTitleCoverAuthor}
    

    would do no good either, because you'd get, when loopTitleCoverAuthor has the value 1,

    \ifdefined\AuthorName A
    

    and not a single token as you're hoping to.

  3. Similarly, when you do

     \expandafter\AuthorName\Alph{loopTitleCoverAuthor}
    

    in the true part, you get two tokens, not \AuthorNameA.

How can you do?

The trick is using \ifcsname and \csname. You first want to produce a token whose name consists of AuthorName followed by the alphabetical value of the counter:

\ifcsname AuthorName\Alph{loopTitleCoverAuthor}\endcsname
  \expandafter\AuthorName\Alph{loopTitleCoverAuthor}
  \textsc{\csname AuthorSurname\Alph{loopTitleCoverAuthor}\endcsname}\\
\fi

No \expandafter is needed, because \ifcsname and \csname perform full expansion until the matching \endcsname is found.

  • Bonus points for kind explanation. If I could I would accept 2 answers as this one would surely also brought me to a working document. Thank you! – Nejc Draganjec Apr 22 '16 at 19:54
  • @NejcDraganjec Don't worry! I'm no short in rep. ;-) – egreg Apr 22 '16 at 19:55

Though there are already good answers, I contribute the version, I used for my currently growing Liederbuch-package:

\def\TesT#1{
\expandafter\def\csname test\Alph{#1}\endcsname{}
}

\newcounter{wseva}
\setcounter{wseva}{4}

\TesT{wseva}

\def\doesItExist#1{
\expandafter\ifx\csname test\Alph{#1}\endcsname\relax
no
\else
yes
\fi
}

\begin{document}

\doesItExist{wseva}

\end{document}

If the content of \csname doesnt exist, it returns \relax. The comparison \ifx\theExpandedCsname\relax return true. Otherwise it returns false and the \else part will be run.

  • What happens if you say \doesitexist{undefined}\doesitexist{undefined}? – Manuel Apr 22 '16 at 22:21
  • @Manuel You have to make a counter named undefined first. Then it says no. – MaestroGlanz Apr 23 '16 at 8:55

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.