1

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 :(

1

2 Answers 2

2

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

3
  • I would consider implementing the LaTeX3 version using a property list (one variable, lots of sub-entries).
    – Joseph Wright
    Jan 29, 2013 at 7:14
  • @JosephWright. Thanks for the suggestion. Makes for more transparent code.
    – A.Ellett
    Jan 29, 2013 at 13:44
  • @A.Ellett Use ~ to denote spaces in messages, not "backslash-space"; just remember not to put them at the start of a line.
    – egreg
    Jan 29, 2013 at 14:26
0

To your first question: You can define a macro T1, but that doesn't help you since you can't call it with the backslash syntax. See the following example:

\documentclass{minimal}

\begin{document}
\expandafter\def\csname T1\endcsname{Test 1}
\expandafter\def\csname T2\endcsname{Test 2}

\csname T1\endcsname

\csname T2\endcsname

\T1
\end{document}

You could define a macro \def\T#1{code} instead and use a if-then structure or similar to print different questions dependent on the argument. You could call it with \T1, \T2, ... ¸\T9 but for higher values you need braces: \T{13}.

For the second question, a minimal (not) working example would help.

You must log in to answer this question.

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