传递变量的字符串值

传递变量的字符串值

MWE 下面的程序使用exsheets包打印书末问题的答案。代码无法正常工作,因为它似乎是一个扩展问题。当\SetQuestionProperties{section-title= \secName }我将 \secName 变量放在One第一部分和Two第二部分中时,而不是 ,一切都正常(即,将前几次出现的“\secName”替换为“One”,将接下来几次出现的“\secName”替换为“Two”)。
有人知道如何使此代码正常工作,以便正确地将 \secName 变量的字符串值传递给 \SetQuestionProperties 吗?

当前结果是“第 节 答案 1). foo 2). bar 第 节 答案 1). baz 2). foobar”,它应该是Section One 1). foo 2). bar Section Two 1). baz 2). foobar

\documentclass{scrartcl}
\usepackage{exsheets}
\setlength{\parindent}{0pt}

\SetupExSheets{counter-within=section}
\DeclareQuestionProperty{section-title}
\SetupExSheets{counter-within=section ,
         headings=inline-nr ,
         counter-format=qu).}
\SetupExSheets{section-hook = \noindent\bfseries
          Section \GetQuestionProperty{section-title}{\CurrentQuestionID}
          \space}

\newcommand{\secName}{}
\newcommand{\lsection}[1]
           {
           \renewcommand{\secName}{#1}
           \section{#1}
           }



\begin{document}


\lsection{One}

\begin{question}
 \SetQuestionProperties{section-title= \secName } 
  say foo
\end{question}
\begin{solution}
  foo
\end{solution}

\begin{question}
  \SetQuestionProperties{section-title= \secName }
  say bar
\end{question}
\begin{solution}
  bar
\end{solution}

\lsection{Two}

\begin{question}
  \SetQuestionProperties{section-title= \secName }
  say baz
\end{question}
\begin{solution}
  baz
\end{solution}

\begin{question}
\SetQuestionProperties{section-title= \secName }
  say foobar
\end{question}
\begin{solution}
  foobar
\end{solution}

\lsection{Answers}

\printsolutions

\end{document}

答案1

确实在\SetQuestionProperties{ section-title = \secName }宏中\secName需要扩展一次。否则问题属性章节标题设置为令牌,\secName它仅在\printsolutions其当前定义的位置使用时才会扩展Answers(这是您在示例中看到的)。

扩展 token 的常用方法是使用\expandafter。这在这里很有用,但很繁琐:我们需要跨越 16 个 token:

\expandafter\SetQuestionProperties\expandafter{\expandafter
  s\expandafter e\expandafter c\expandafter t\expandafter
  i\expandafter o\expandafter n\expandafter-\expandafter
  t\expandafter i\expandafter t\expandafter l\expandafter
  e\expandafter=\secName
}

因此,更好的选择是另一种常用的解决方案:定义一个临时宏(\x),使用\edef它来彻底扩展替换文本。为了只扩展\secName一次,我们可以使用\unexpanded\expandafter{\secName}

\begingroup
\edef\x{\endgroup
  \SetQuestionProperties{
    section-title = \unexpanded\expandafter{\secName}
  }}\x

\SetQuestionProperties不可扩展,因此无需担心。)但是,exsheets是用 expl3 编写的,并且已经有一个\SetQuestionProperties扩展其参数的版本:\exsheets_set_question_properties:x。我们只需要使其在 expl3 语法之外可用:

\ExplSyntaxOn
\NewDocumentCommand \SetQuestionPropertiesX {m}
  { \exsheets_set_question_properties:x {#1} }
\ExplSyntaxOff

在下面的例子中,我也使用了,pre-body-hook所以我不更改每个开头的行question

\documentclass[parskip=half]{scrartcl}
\usepackage{exsheets}
% \setlength{\parindent}{0pt} please don't use this but rather KOMA-Script's
% `parskip' option

\ExplSyntaxOn
\NewDocumentCommand \SetQuestionPropertiesX {m}
  { \exsheets_set_question_properties:x {#1} }
\ExplSyntaxOff

\DeclareQuestionProperty{section-title}
\SetupExSheets{
  counter-within = section ,
  headings       = inline-nr ,
  counter-format = qu). ,
  section-hook   =
    \noindent\bfseries Section
    \GetQuestionProperty{section-title}{\CurrentQuestionID}\space ,
  question/pre-body-hook =
    \SetQuestionPropertiesX{ section-title = \unexpanded\expandafter{\secName} }
}

\newcommand{\secName}{}
\newcommand{\lsection}[1]{\renewcommand*{\secName}{#1}\section{#1}}

\begin{document}

\lsection{One}

\begin{question}
  say foo
\end{question}
\begin{solution}
  foo
\end{solution}

\begin{question}
  say bar
\end{question}
\begin{solution}
  bar
\end{solution}

\lsection{Two}

\begin{question}
  say baz
\end{question}
\begin{solution}
  baz
\end{solution}

\begin{question}
  say foobar
\end{question}
\begin{solution}
  foobar
\end{solution}

\lsection{Answers}

\printsolutions

\end{document}

在此处输入图片描述

答案2

这是一个“非法”的答案,因为我提出的代码依赖于定义内部命令的变体。这个答案主要是为了给包开发人员提供思路。

我定义了一个命令\DeclareQuestionPropertyFixed,该命令以属性名称和应从中获取值的变量作为参数,在本例中

\DeclareQuestionPropertyFixed{section-title}{\secName}

所以人们只需做

\SetupExSheets{
  ...
  question/pre-body-hook = \SetQuestionProperties{section-title},
}

完整代码。

\documentclass[parskip=half]{scrartcl}
\usepackage{exsheets}

\ExplSyntaxOn
\NewDocumentCommand \DeclareQuestionPropertyFixed { m m }
 {
  \exsheets_declare_question_property:n {#1--fixed}
  \keys_define:nn { question / meta }
   {
    #1 .code:n = \__exsheets_question_set_property:nV { #1--fixed } #2
   }
 }
\cs_generate_variant:Nn \__exsheets_question_set_property:nn {nV}
\ExplSyntaxOff

\DeclareQuestionPropertyFixed{section-title}{\secName}
\SetupExSheets{
  counter-within = section ,
  headings = inline-nr ,
  counter-format = qu). ,
  section-hook = \noindent\bfseries Section 
                 \GetQuestionProperty{section-title}{\CurrentQuestionID}\space ,
  question/pre-body-hook = \SetQuestionProperties{section-title}
}

\newcommand{\secName}{}
\newcommand{\lsection}[1]{\renewcommand*{\secName}{#1}\section{#1}}

\begin{document}

\lsection{One}

\begin{question}
  say foo
\end{question}
\begin{solution}
  foo
\end{solution}

\begin{question}
  say bar
\end{question}
\begin{solution}
  bar
\end{solution}

\lsection{Two}

\begin{question}
  say baz
\end{question}
\begin{solution}
  baz
\end{solution}

\begin{question}
  say foobar
\end{question}
\begin{solution}
  foobar
\end{solution}

\lsection{Answers}

\printsolutions

\end{document}

在此处输入图片描述

相关内容