使用幻像标签来保存复杂且动态定义的宏

使用幻像标签来保存复杂且动态定义的宏

我已经尝试这样做了一段时间,但似乎出现了一些我不太明白的错误。这是尝试使用建议的后续操作这里但我认为这个后续问题有点太复杂了,不适合添加到这个问题中,所以我在这里提出了一个新的问题。

我正在使用一个非常复杂的包这里,但特别重要的是ProblemSelection.sty其中的“ ”,可以看出这里

我在最后包含了一组用于工作流示例的“文件”,但如果不下载包,我怀疑它是否可编译。如果您决定尝试,这些文件应该可以工作(在 Linux 中),尽管您可能需要一些空文件,具体取决于宏还\Master@Input@Test需要什么。一个有用的提示;如果您确实让它与实际包一起工作,\Verbosetrue触发(大量)详细信息写入输出以跟踪问题选择和分配过程,以查看工作流中是否存在故障,我将其作为错误查找代码放入其中。无论如何,我将尝试在此处解释该过程。

本质上,问题选择包旨在过滤分布在大量文件中的大量问题列表,并根据某些过滤属性 ( filter.sty) 随机挑选一些问题。然后,它将问题的内容保存到自定义宏中,稍后可用于显示问题。这主要是使用“ \latexProblemContent”命令包装每个问题和“ \QuestionSelect”根据过滤器查找问题,对它们进行打乱 ( \ChooseQuestions) 并分配命令(\latexProblemContent当宏检测到正确的问题时在宏内完成),最后我们使用\listQuestions列出迄今为止选定的所有问题。所有这些都是使用计数器和动态命名(稍后调用)命令来完成的\roman\Roman到目前为止,所有这些都运行良好。

但是,有时能够重新编译作业而不更改问题会很好(例如,如果我们只想更改作业名称)。本着这种精神,我提出了我的问题(链接在上面),并被引导到幻影标签来包含内容。

理想情况下,我会创建一个标签来保存问题内容,​​然后为它分配一个宏名称,以便稍后调用\latexProblemContent。然后我可以有一个标志,例如,\ifquestions@Static以便标记是否要保留相同的问题。如果我想保留相同的问题,我会从标签中提取问题,如果不是,那么我会提取新的随机问题。

不幸的是,尽管我尽力尝试,但似乎在尝试执行此操作时遇到了各种奇怪的错误,这些错误对我来说都没有任何意义。我猜这与某种扩展问题有关,因为问题本身的内容(内容里面\latexProblemContent) 在尝试写出时可能无法很好地扩展?老实说,我完全无法理解,因为我从未处理过将内容写入文件(aux或其他方式)以获得持久内容。\write命令(及其变体)似乎很简单,但我收到的错误大多数时候都没有什么帮助。

需要明确的是,我的目标是让它的工作方式大致相同,但能够传递可选标志或其他项目,以使其\QuestionSelect调用上次编译的列表,并且最好让它持续到新的编译(没有静态标志)替换这些问题。我不确定如何将标签内容设置为(整个)内容而不\latexProblemContent强制扩展内部任何内容,而且标签本身需要有一些扩展\roman\Roman标记,这似乎很讨厌,尽管我认为我应该能够最终通过适当使用来解决这个问题\expandafter

对于该ProblemSelect.sty文件,我深表歉意,它的增长相当迅速,肯定需要进行一些清理,但我在编写它时尝试将其记录得相当好,以便我(和其他人)能够弄清楚所有事情都在做什么。

示例工作流程:

保存的名为“Series-Compute-0001.tex”的文件/users/local/etc/Series/如下所示:

\ProblemFileHeader{2}% Process how many problems are in this file and how to detect if it has a desirable problem
\ifproblemToFind% If it has a desirable problem search the file.
%%\tagged{Ans@ShortAns, Type@Compute, Topic@Series, Sub@Geometric, Sub@Convergence, File@0001}{
\latexProblemContent{
\begin{problem}
Determine if the series converges or diverges.  If it converges, find its sum. 

\[\sum_{n=0}^\infty {-2 \, \left(\frac{4}{9}\right)^{n}}\]

\begin{multipleChoice}
\choice{Diverges}
\choice[correct]{Converges}
\end{multipleChoice}


\begin{problem}

\[\sum_{n=0}^\infty {-2 \, \left(\frac{4}{9}\right)^{n}} = \answer{-\frac{18}{5}}\]
\end{problem}

\end{problem}}%}

\latexProblemContent{
\begin{problem}
Determine if the series converges or diverges.  If it converges, find its sum. 

\[\sum_{n=0}^\infty {7 \, \left(\frac{5}{8}\right)^{n}}\]

\begin{multipleChoice}
\choice{Diverges}
\choice[correct]{Converges}
\end{multipleChoice}


\begin{problem}

\[\sum_{n=0}^\infty {7 \, \left(\frac{5}{8}\right)^{n}} = \answer{\frac{56}{3}}\]

\end{problem}
\end{problem}}%}
\fi%    This ends the \ifproblemToFind conditional at the top of the problem file.
\ProblemFileFooter

\users\local\etc 中的 Series-Input.tex 如下所示:

\tagged{ Topic@Series, Type@Compute, Ans@ShortAns, Sub@Convergence, Sub@Geometric, File@0001}{
    \select@Question{/users/local/etc/Series/Series-Compute-0001.tex}
}

作业文件如下:

\documentclass[]{ximera}

\usepackage{PackageLoader}% Included in the package linked above in the UF-Problem-Filter file.
\renewcommand{\QBank@loc}{/users/local/etc/}
\makeatletter
\begin{document}
\QuestionSelect{Topic@Series}{File@0001}{1}% Get the problem
\listQuestions% List the problems you found

\end{document}

答案1

在更深入地研究 Google 之后,我确定了如何做到这一点,并认为我会提交一个答案,以防其他人因为类似的原因偶然发现这一点。

我需要的神奇命令是 \unexpanded 命令,它接受一个可能很长的参数(比如具有多个命令的整个问题)并将其按原样写入外部文件。

因此,我在包顶部添加了一个 \newwrite\ProblemList,但(重要的是)没有打开包顶部的文件。然后,在 \latexProblemContent 命令中,当它找到所需的问题并为其分配一个稍后要调用的宏时,我同时使用该命令将问题写出到文件中;

\immediate\write\ProblemList{\unexpanded{#1}}

\immediate 确保问题在定义时写入,从而避免最后出现一堆重复的问题。 \unexpanded 确保问题逐字写入而不展开,从而避免错误。

然后,在 \QuestionSelect 命令(触发所有操作的用户命令)中,我有一个条件来检查我是否正在提取静态问题。因此,命令的开头如下所示;

\ifquestion@Static% Check to see if we want to reuse the old problems.
    \input{ProblemList}
\else
    \immediate\openout\ProblemList=ProblemList.tex
    (Rest of command content)
\fi

在这里,如果 question@Static 标志处于活动状态,那么我只需输入(大概)已经制作好的问题列表。否则,我然后打开文件 ProblemList.tex 进行写入,它会立即用空白文件覆盖其中的所有内容,然后再用更多问题填充该空白文件。

以下是与用例相关的一些注意事项,我目前并不担心,但对于其他尝试做类似事情的人来说可能很重要:

  1. 当我打开文件进行写入时,问题是,如果调用多个 \QuestionSelects,那么最后一个将覆盖所有前面的,并且您将只会重复获得同一组问题,而不是所有问题。(我可能会使用动态创建的写入文件来解决这个问题。或者,能够以某种方式构建写入文件以检查它是否已经打开,并附加某种检查以在正确的位置调用正确的问题块,这将是很好的)。
  2. 如果您尝试在未先编译的情况下调用静态问题,则可能会出错,因为没有文件可以输入(应该可以通过某处的条件来修复)
  3. 这有点明显,但只有当您保存自定义输出文件时,这才会省去问题。如果您有可以为您清理“额外文件”的东西,您可能会删除静态列表,而这不会有任何效果。

如果我(或其他任何人)对上述两个用例提出了好的解决方案,我会附上答案,但这在功能上是我目前所追求的。

相关内容