LaTeX3:函数范围

LaTeX3:函数范围

如果我没理解错的话,token 列表是全局声明的,但可以在本地赋值。因此,所有同名的局部变量实际上都是全局声明为同一个变量。函数经常需要使用局部变量,很难确保这些局部变量没有名称冲突。例如:

\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn

\tl_new:N \l_module_my_tl

%%  Example 1: A function group is wanted.

\cs_new:Npn \module_outer:
{
    \tl_set:Nn \l_module_my_tl { outer }
    \tl_show:N \l_module_my_tl
    \module_inner:
    \tl_show:N \l_module_my_tl
}

\cs_new:Npn \module_inner:
{{  %%  If you change this to { you'd get wrong result.
    \tl_show:N \l_module_my_tl
    \tl_set:Nn \l_module_my_tl { inner }
    \tl_show:N \l_module_my_tl
}}  %%  If you change this to } you'd get wrong result.

\module_outer:

%%  Example 2: A function group is unwanted.

\cs_new:Npn \module_tokens:
{   %%  If you change this to {{ you'd get wrong result.
    { 1 } { 2 } { 3 }
}   %%  If you change this to }} you'd get wrong result.

\tl_set:Nx \l_module_my_tl { \module_tokens: }
\tl_show:N \l_module_my_tl

\ExplSyntaxOff
\end{document}

在此代码的第一个示例中,外部函数和内部函数都使用相同的标记列表\l_module_my_tl。不幸的是,内部函数中的更改会传播到外部函数,这是不受欢迎的。一个简单的解决方案是为内部函数添加一个函数级组。

但是如果函数有输出,这个函数级组可能会引起问题,如第二个示例所示。如果添加了函数级组,它会输出{{1}{2}{3}}但不会{1}{2}{3}

什么是一个通用的解决方案(程序员可以遵循而不需要逐案关注的通用惯例)可以使这两个示例都能正常工作?

答案1

在许多编程语言中,例如Lua,函数或条件表达式会构成一个块,并且局部变量的值将在块之后重置。例如

---- lua code ----
local tmp = "a"
print(tmp)          ---- tmp=a
function SomeFun()
  local tmp = "b"
  print(tmp)        ---- tmp=b
  if 1 > 0 then
    local tmp = "c"
    print(tmp)      ---- tmp=c
  end
  print(tmp)        ---- tmp=b
end
SomeFun()
print(tmp)          ---- tmp=a

最近我写道functional基于 的包expl3。在这个包中,你可以通过设置 使每个函数(也是每个条件)成为一个组\Functional{scoping=true}

% --- latex code --- %
\documentclass{article}
\usepackage{functional}
\begin{document}
\Functional{scoping=true}
\IgnoreSpacesOn
\TlSet \lTmpaTl {a}
\TlVarLog \lTmpaTl          % ---- a
\PrgNewFunction \SomeFun { } {
  \TlSet \lTmpaTl {b}
  \TlVarLog \lTmpaTl        % ---- b
  \IntCompareTF {1} > {0} {
    \TlSet \lTmpaTl {c}
    \TlVarLog \lTmpaTl      % ---- c
  }{ }
  \TlVarLog \lTmpaTl        % ---- b
}
\SomeFun
\TlVarLog \lTmpaTl          % ---- a
\IgnoreSpacesOff
\end{document}

虽然 中有函数expl3,但对它们的求值是从外到内。使用此新包,函数的求值是从内到外,这与其他编程语言(例如或 )functional相同。以下是计算整数平方的另一个示例:LuaJavaScript

---- lua code ----
function MathSquare (arg)
  local lTmpaInt = arg * arg
  return lTmpaInt
end
print(MathSquare(5))
print(MathSquare(MathSquare(5)))
% --- latex code --- %
\documentclass{article}
\usepackage{functional}
\begin{document}
\IgnoreSpacesOn
\PrgNewFunction \MathSquare { m } {
  \IntSet \lTmpaInt { \IntEval { #1 * #1 } }
  \Result { \Value \lTmpaInt }
}
\IgnoreSpacesOff
\MathSquare{5}
\MathSquare{\MathSquare{5}}
\end{document}

Lua你会发现代码和代码之间几乎是一一对应的functional,我想这个包就是你想要的。

相关内容