I'm using the exams
package to generate some exams (engineering). My source files are in Rnw
format so the underlying engine is Sweave.
In R side, I'm using units
package (to check dimensionality correctness) and I've created a function (called units2tex
) to convert a magnitude from units to LaTeX equivalent. So, when I calculate a variable, I have to create a copy for LaTeX:
<<>>=
R = set_units(1,ohm)
I = set_units(1,A)
V = R*I
R_tex = units2tex(R)
I_tex = units2tex(I)
#V_tex = units2tex(V)
@
For $R = \Sexpr{R_tex}$, the answer is \Sexpr{units2tex(V)}.
In both cases (to print R
and V
) I have to explicitly call units2tex
function somewhere. It's is a lot of typing (more to type, more places to be wrong) because there are a lot of steps and intermediate temporal values.
Is it possible to easily create versions of \Sexpr with automatic function calls?
More concretely:
\SexprT{V}
to function like \Sexpr{units2tex(V)}
?\SexprT{V,digits=2}
(or similar) to function like \Sexpr{units2tex(V,digits=2)}
?In both cases without losing the use of original \Sexpr
.
My current options and its cons:
units2tex(...)
and duplicate variables (units version and LaTeX version). It is my current approach. A lot to typing, prone to forget conversions or generate conversions that they are not used latter.\Sexpr{t(V)}
. Difficult to remember the meaning of each translation function. Pollution of the namespace. I still remember last time I use a c
function (after a
and b
ones) and break original c function.*.Rnw2
file and have to create a script in ¿sed? ¿R?, read files, modify values and generate the *.Rnw
file and then call exams2pdf functions... There is problems if I forgot to update Rnw
exams files. I'd use a Makefile to coordinate, but I have to switch between a terminal and Rstudio... This option is, maybe the best (after the creation of \Sexpr
versions) but the solution obscures the pipeline and difficult quick questions generation to check them.So, the best approach is: Is it possible to create variations of \Sexpr?
Full example: file: "question.Rnw"
\usepackage[utf8]{inputenc}
\usepackage[OT1]{fontenc}
<<echo=FALSE, results=hide>>=
library(units)
units2tex <- function(x) {
# this function is not important here. Simplified version the original version much complex
paste0(x,deparse_unit(x))
}
@
\begin{question}
<<echo=FALSE, results=hide>>=
In <- set_units(1e-3,A)
Pn <- set_units(sample(c(2,1,0.5,0.25,0.125),1),W)
In_tex <- units2tex(In)
Pn_tex <- units2tex(Pn)
@
A resistor nah nah nah current $I_n=\Sexpr{In_tex}$ nah, nah, nah $P_n=\Sexpr{Pn_tex}$
What is V?
<<echo=FALSE, results=hide>>=
Vn <- set_units(Pn/In,V)
Vn_tex <- units2tex(Vn)
@
\begin{answerlist}
\item $V = \Sexpr{Vn_tex}$
\item $V = \Sexpr{Pn_tex}$
\item $V = \Sexpr{In_tex}$
\end{answerlist}
\end{question}
\begin{solution}
To calculate $V$, we do $V= P_n/I_n = \frac{\Sexpr{Pn_tex}}{\Sexpr{In_tex}} = \Sexpr{Vn_tex}$
\begin{answerlist}
\item Ok
\item Bad
\item Wrong
\end{answerlist}
\end{solution}
\exname{question1}
\extype{schoice}
\exsolution{100}
\exshuffle{TRUE}
And to compile:
library(exams)
exams2html(c("question1.Rnw"), encoding="utf-8",template='plain8.html',mathjax = TRUE)
In Rnw exercises the content of \Sexpr{}
is turned into character by explicitly calling as.character()
on it. As this is a generic function you could easily define your own method, say,
as.character.units <- function(x, ...) units2tex(x, ...)
and then simply using \Sexpr{V}
will automatically call your units2tex()
function behind the scenes.
Note that the same does not work for Rmd exercises. So i you want to mix Rnw and Rmd exercises, then using a shortcut function name such as the following might be better:
u2t <- function(x, ...) units2tex(x, ...)
This would then need to be called as \Sexpr{u2t(V)}
and `r u2t(V)`
, respectively.