为在宏外部运行的代码创建宏时出现失控参数错误

为在宏外部运行的代码创建宏时出现失控参数错误

我确信我的问题是由于我几乎完全不了解 LaTeX 的扩展规则……

我写了一些代码,使用 SageTeX 包来跟踪家庭作业问题的答案列表,然后在最后将它们全部打印出来。以下是其中一部分的示例:

\begin{sagesilent}
class AnswerList:
    def __init__(this):
        this.answers = []
    def _latex_(this):
        result = "\\begin{answers}\n"
        for answer in this.answers:
            result += "    \\item " + str(answer) + "\n"
        result += "\\end{answers}\n"
        return result
    def next(this, answer):
        this.answers.append(answer)
answerlist = AnswerList()
\end{sagesilent}

这在我的 LaTeX 文档中编译得很好。然后我使用其他 SageTeX 命令将答案(按顺序)添加到此对象,然后在最后自动打印它们,它会产生所需的结果。但是,我希望将所有编程移到单独文件中的宏中,以使其更可重复使用并保持我的 LaTeX 文档整洁。因此,我创建的一个宏是:

\newcommand{\makeanswers}{%
\begin{sagesilent}
class AnswerList:
    def __init__(this):
        this.answers = []
    def _latex_(this):
        result = "\\begin{answers}\n"
        for answer in this.answers:
            result += "    \\item " + str(answer) + "\n"
        result += "\\end{answers}\n"
        return result
    def next(this, answer):
        this.answers.append(answer)
answerlist = AnswerList()
\end{sagesilent}
}

然后我将第二个文档包含到我的第一个文档中(使用命令\input),并在我进入主 LaTeX 文件中的文档环境后立即调用\makeanswers。当我尝试编译文档时,我收到失控参数错误。

有没有办法创建一个宏来插入这段 LaTeX 代码?这里可能有一种更适合 LaTeX、更少依赖 Python 的方法来解决我的问题,但这是我所知道的……

答案1

您应该能够使用 来使用它sagetex,但纯 LaTeX 解决方案可能是最好的,而且应该不会太难。以下是使用 的一些想法sagetex,然后是纯 LaTeX 解决方案。

您是否尝试过将 放入sagesilent外部文件中而不将其包装在宏中?我认为这样做可行。您可能需要\input身体该文件,因为sagesilent在序言中似乎不起作用。

我没有 Sage 来测试,但这里有一个与我的相当的pythontex包。如果你pycodesagesilent\pyc替换我的\sagestr(也许去掉print()),事情可能会成功,或者至少接近成功。我对\addanswer宏的定义假设你的答案不会包含#%(或者可能包含 的其他几个特殊字符sagetex)。你应该能够将类定义和宏定义放在外部文件中,然后\input放在文档中身体(再次,sagesilent似乎不喜欢序言......顺便说一句,pythontex没有那个限制)。

\documentclass{article}

\usepackage{pythontex}

\newenvironment{answers}{\begin{enumerate}}{\end{enumerate}}

\begin{document}

\begin{pycode}
class AnswerList:
    def __init__(this):
        this.answers = []
    def _latex_(this):
        result = "\\begin{answers}\n"
        for answer in this.answers:
            result += "    \\item " + str(answer) + "\n"
        result += "\\end{answers}\n"
        return result
    def next(this, answer):
        this.answers.append(answer)
answerlist = AnswerList()
\end{pycode}

\newcommand{\addanswer}[1]{\pyc{answerlist.next("#1")}}
\newcommand{\printanswers}{\pyc{print(answerlist._latex_())}}

\addanswer{123}

\addanswer{345}

\printanswers

\end{document}

这是一种不需要任何外部 Python 程序的方法。您可以根据需要修改类似的东西。

\documentclass{article}

\makeatletter
\newcommand{\storedanswers}{}
\newcommand{\addanswer}[1]{\g@addto@macro\storedanswers{\item #1}}
\newcommand{\makeanswers}{%
    \begin{enumerate}
    \storedanswers
    \end{enumerate}
}
\makeatother

\begin{document}

\addanswer{123}

\addanswer{345}

\makeanswers

\end{document}

答案2

如果您发布完整的文档而不是片段,这会有所帮助,尽管我认为我没有那个包,但如果它正在执行我假设的操作,那么像这个未经测试的代码之类的东西可能会起作用。

\catcode`Z=0
\catcode`\\=12

Znewcommand{Zmakeanswers}{%
Zbegin{sagesilent}
class AnswerList:
    def __init__(this):
        this.answers = []
    def _latex_(this):
        result = "\\begin{answers}\n"
        for answer in this.answers:
            result += "    \\item " + str(answer) + "\n"
        result += "\\end{answers}\n"
        return result
    def next(this, answer):
        this.answers.append(answer)
answerlist = AnswerList()
\end{sagesilent}
}
Zcatcode`Z\=0

相关内容