嵌套宏调用-语法错误?

嵌套宏调用-语法错误?

Argument of \\drs has an extra }.当我尝试处理以下内容时,出现以下信息:

\documentclass{article}

\usepackage{tikz}

\newcommand{\drs}[2][lambda/.initial={}]{%
  \{%
  {\pgfkeys{/drs/.cd, #1, print}}%
  \}%
}

\pgfkeys{/drs/.cd,
  print/.code = {\pgfkeysvalueof{/drs/lambda}},
  lambda/.code = {%
    \pgfkeys{/drs/.cd,
             list/.list = {#1},
    }%
  },
  list/.code = {\pgfkeys{/drs/lambda/.append = (#1)}}
}

\begin{document}

  \drs[lambda={a,b,{\drs[lambda={x}]{Bar}}}]{Foo}

\end{document}

但括号的数量是正确的。我怀疑这与宏扩展的顺序有关。

任何帮助将不胜感激。

编辑:发现一个相关错误(我认为):

\documentclass{article}

\usepackage{tikz}

\makeatletter
\pgfkeys{/drs/.cd,
  %
  % lambda
  %
  lambda/.code={%
    \pgfkeys{/drs/.cd,
      lambda list/.list={#1},
      lambda string
    }%
  },
  lambda list/.code={\pgfkeys{/drs/lambda/.append={$\lambda$#1.}}},
  lambda string/.code=\def\draw@drs@lambda{\pgfkeysvalueof{/drs/lambda}},
  %
  % presupposition
  %
  presupposition/.code={%
    \pgfkeys{/drs/.cd,
      presupposition list/.list={#1},
      presupposition string
    }%
  },
  presupposition list/.code={\pgfkeys{/drs/presupposition/.append={#1}}},
  presupposition string/.code={\def\draw@drs@presupposition{\pgfkeysvalueof{/drs/presupposition}}},
}

\newcommand{\drs}[2][]{%
  \begingroup%
    \def\mymacroempty{}%

    % DRS building blocks
    \def\draw@drs@presupposition{}%
    \def\draw@drs@lambda{}%

    \pgfkeys{/drs/.cd,
      presupposition/.initial={},
      lambda/.initial={},
      #1
    }%

    [ presupposition: \draw@drs@presupposition ]%
  \endgroup%
}
\makeatother

\begin{document}

  \drs[presupposition={\drs[presupposition={m}]{}}]{%
    Foo%
  }

\end{document}

一切按预期进行,并打印出来

[ presupposition: [ presupposition: m]]

向嵌套\drs调用添加 lambda 选项

  \drs[presupposition={\drs[lambda=x,presupposition={m}]{}}]{%
    Foo%
  }

生产

  [ presupposition: [ presupposition: ]]

嵌套的预设被吞噬了。我猜这又和扩展时间有关,但我不知道该如何修复它。:-)

答案1

这是一个微妙的!

当前的问题出在这一行:

list/.code = {\pgfkeys{/drs/lambda/.append = (#1)}}

一些测试表明这\pgfkeys被视为=特殊事物。因此,任何带有的东西都=必须受到保护。您可以使用以下方法进行测试:

\pgfkeys{/drs/lambda/.append = hello=world}
\pgfkeys{/drs/lambda/.show value}
\pgfkeys{/drs/lambda/.append = {hello=world}}
\pgfkeys{/drs/lambda/.show value}

第一次,只会hello显示在日志中。第二次,我们得到全部hello=world。因此,由于\drs...列表中的位包含=,因此需要对其进行保护。

乍一看,你似乎已经这样做了,因为你是{\drs[lambda={x}]{Bar}}列表中的一个术语。但再多做一些实验就会发现,/.list迭代器会剥离所有分组,那么实际上传递的是\drs[lambda={x}]{Bar}调用:

\pgfkeys{/drs/lambda/.append = (\drs[lambda={x}]{Bar})

这会触发错误。直接的解决方案是在list/.code代码中加上括号:

list/.code = {\pgfkeys{/drs/lambda/.append = {(#1)}}}

测试的值/drs/lambda表明它现在得到了正确的东西。

但是,修复这个问题后,你会发现你的程序有一个小问题!由于扩展的顺序,内部\drs执行最外层的一个,因此它将 视为(a)(b)(\drs[lambda={x}]{Bar})的初始值/drs/lambda,向其添加一个\{(x)\},然后再次打印出完整值:(a)(b)(\drs[lambda={x}]{Bar})\{(x)\}。其中包含对 的另一个调用\drs。等等。等等。

您可以尝试通过在附加之前完全展开列表的参数来反转扩展顺序,#1但我遇到了麻烦(我不完全理解,但似乎与 LaTeX 处理带有可选参数的命令的方式有关)。另一种方法是/drs/lambda在每次调用时都将其清空drs,因为在执行内部调用时,外部调用已经完成其工作并且不再需要。有几种(等效)方法可以做到这一点。例如,

\newcommand{\drs}[2][lambda/.initial={}]{%
  \{%
  {\pgfkeys{/drs/.cd, lambda/.initial={}, #1, print}}%
  \}%
}

(这反而违背了默认参数的目的,因此可以将其删除。)

通过这两项修改,我得到:

{(a)(b)({(x)})}

用于输出。

更新:(回答更新后的问题)。第二个问题也是关于分组(而不是扩展)。当被.list调用时,它会看到:

\drs [presupposition={m},lambda={a}]{}

就它而言,逗号是公平的。方括号定义的伪分组被忽略,因为它不是真正的分组。因此它将其拆分为\drs[presupposition={m}lambda={a}]{}。这会弄乱以下内容。

修复这个问题取决于你还想用这些宏实现什么目的,以及你希望能够处理哪些其他类型的输入。最简单的修复方法是让宏\drs有两个强制参数,而不是一个可选参数和一个强制参数。这将确保内部调用的参数\drs受到保护,不会被外部调用拆分。另一种方法是在参数中使用键值对,从而\drs获得单身的参数是一个列表,然后由 进行处理\pgfkeys

相关内容