[Tex/LaTex] Regarding variable names and values of variables inside macros

macros

I have to questions that I'd like to solve since I'm trying to build up a macro for my examination duties here.
The first one is: is there a way to include numbers in the definition of variables? Say I'm writing a test exam consisting of 10 questions, and I want to assign a variable \T1 the answer to question 1, a variable \T2 the answer to question2, etc. Obvious things like

\def\T1{answer 1}
\def\T2{answer 2}

or similar with \newcommand doesn't work. Is there a properway to use numbers in variable definitions?

Second question is: I have a macro that calls a second macro that defines a variable on it. WHen I try to access the value of the variable defined in the innermost macro, from the main code, the system complains. Is then a way to save variable names and values in macros, such that one can access them from outside?

Thanks and sorry for my poor TeX/LaTeX knowledge 🙁

Best Answer

There are a couple of approaches you can take. Here is a solution which makes use of TeX's \ifcase which can be very nice for this sort of thing:

\documentclass{article}
\usepackage[margin=1in]{geometry}
\newcounter{examquestion}
\newcommand{\question}{\stepcounter{examquestion}\noindent\textbf{Q\theexamquestion.)}\hspace*{1em}}
\newcommand{\answers}[1][\theexamquestion]{%
    \ifcase#1\relax{This would be the answer to question 0: I presume there is no question 0}
                   \or{Answer to question 1}%
                   \or{Answer to question 2}%
                   \or{Answer to question 3}%
                   \or{Answer to question 4}%
                   \fi}%'
%% for purposes of this example only
\usepackage{lipsum}
\pagestyle{empty}
\begin{document}
\question \lipsum[1]
    \par\hspace*{\fill}\textbf{Answer: \answers}
    \vspace{0.25in}

\question \lipsum[2]
    \par\hspace*{\fill}\textbf{Answer: \answers}
    \vspace{0.25in}

\question \lipsum[3]
    \par\hspace*{\fill}\textbf{Answer: \answers}
    \vspace{0.25in}

Summary:
\begin{itemize}
\item  \answers[1]
\item  \answers[2]
\item  \answers[3]
\end{itemize}


\end{document}

This works nicely if you have a counter for each problem. I've written the \answers command so that it defaults to using the current value of question counter examquestion. But you can override this. As you may notice, I've answered each question when the answer is posed. Maybe this is not what you wanted to do. I've allowed you to overwrite this default. I've illustrated this in the itemized summary.

enter image description here

LaTeX3 answer with a better user interface:

\documentclass{article}
\usepackage[margin=1in]{geometry}
\usepackage{xparse}
\ExplSyntaxOn
%% expl3::warnings and error messages
\msg_new:nnnn {examanswer}{answer_already_defined}{%
                           You're\ attempting\ to\ define\ an\ answer\ that\ 
                           already\ exists.\\
               \\
                           \ \ \ \ Key\ "#1"\ already\ exists.
                           }{}
\msg_new:nnnn {examanswer}{answer_not_defined}{%
                           You're\ attempting\ to\ call\ an\ answer\ that\ 
                           has\ not\ been\ defined.\\
               \\
                           \ \ \ \ Key\ "#1"\ does\ not\ exist.}{}
%% expl3 code to save and retrieve answers
\prop_new:N \g__answers_to_exam_problems_plist
\cs_new_protected:Npn \__setting_answers_cs:nn #1#2 {
    \prop_if_in:NnTF \g__answers_to_exam_problems_plist {#1}
    {
        \msg_error:nnx{examanswer}{answer_already_defined}{#1}
    }
    {
        \prop_gput:Nnn \g__answers_to_exam_problems_plist {#1} {#2}
    }    
}
\cs_new_protected:Npn \__getting_answers_cs:n #1 {
    \prop_if_in:NnTF \g__answers_to_exam_problems_plist {#1}
    {
        \prop_get:Nn \g__answers_to_exam_problems_plist {#1}
    }
    {
        \msg_error:nnx {examanswer}{answer_not_defined}{#1}
    }
}   
%% user interface to save and retrieve answers
\NewDocumentCommand{\saveanswer}{ m m }{
    \__setting_answers_cs:nn {#1}{#2}
}
\NewDocumentCommand{\getanswer}{ m }{
    \__getting_answers_cs:n {#1}
}
\ExplSyntaxOff
%% a bit of the old version:  here purely for the sake of illustration
\newcounter{examquestion}
\newcommand{\question}{\stepcounter{examquestion}\noindent\textbf{Q\theexamquestion.)}\hspace*{1em}}
%% for purposes of this example only
\usepackage{lipsum}
\pagestyle{empty}
\begin{document}
\question \lipsum[1]
    \saveanswer{q1ans}{This is the answer to question 1}
    \vspace{0.25in}

\question \lipsum[2]
    \saveanswer{q2ans}{Answer to question 2}
    \vspace{0.25in}

\question \lipsum[3]
    \saveanswer{Q:supplementary angles}{$m\angle{ABC}=30$}
    \vspace{0.25in}

Summary:
\begin{itemize}
\item  \getanswer{q1ans}
\item  \getanswer{q2ans}
\item  \getanswer{Q:supplementary angles}
\end{itemize}

\end{document}

This approach, I think, is better. It allows you to name the answers to a particular problem independent of the actual numbering of the problems: in this example I nevertheless gave the most answers names which corresponded to the order in which the questions were asked. But there's no reason this code won't let you write,

\setanswer{Q:supplementary angles}{$m\angle{ABC}=30$}

and then later call it with

\getanswer{Q:supplementary angles}

I'd prefer this naming convention since it is more descriptive: and, if later you rearrange the problems, figuring out the meaning of the cryptic \T1 or \getanswer{q1ans} won't be such a hassle.

I've also added some bells and whistles to make sure you don't overwrite previously defined answers and to warn you when calling an undefined answer.

enter image description here