这是扩展大师的一本书。我试图使用切换代数向同事展示你可以在 LaTeX 中做到这一点。我想使用括号,因为它类似于正常的函数调用(但事实并非如此)。这适用于 0 和 1 个参数,但我该如何处理递归调用和宏?有时我会得到一个额外的右括号。当使用递归调用时,我认为#1
应该#2
完全展开。
其行为\band
是,如果两个参数都是 1,则输出才为 1,否则结果为 0。
\documentclass[a4paper]{article}
\makeatletter
\def\band(#1,#2){\@band{#1}{#2}}
\def\@band#1#2{\ifnum#1=0 0\else\ifnum#2=0 0\else 1\fi\fi}
\makeatother
\begin{document}
\band(0,0) % works
\band(0,1) % works
\band(1,0) % works
\band(1,1) % works
\band(\band(1,1),1) % works
\band(0,\band(1,1)) % doesn't work
\band(\band(1,1),\band(1,1)) % works
\band(\band(0,1),\band(1,1)) % doesn't work
\def\x{1}
\def\y{0}
\band(\y,\band(\x,\x)) % doesn't work
\band(\band(\x,\y),\y) % works
\end{document}
答案1
实现自动嵌套控制的一个简单方法是使()
tex 分组字符如下{}
\documentclass[a4paper]{article}
\makeatletter
\def\band#1{\@band#1\relax}
\def\@band#1,#2\relax{\ifnum#1=0 0\else\ifnum#2=0 0\else 1\fi\fi}
\makeatother
\newenvironment{bands}{\catcode`\(=1\catcode`\)=2 }{}
\begin{document}
\begin{bands}
\band(0,0) % works
\band(0,1) % works
\band(1,0) % works
\band(1,1) % works
\band(\band(1,1),1) % works
\band(0,\band(1,1)) % doesn't work
\band(\band(1,1),\band(1,1)) % works
\band(\band(0,1),\band(1,1)) % doesn't work
\def\x{1}
\def\y{0}
\band(\y,\band(\x,\x)) % doesn't work
\band(\band(\x,\y),\y) % works
\end{bands}
\end{document}
答案2
这是一个很长的评论。我只想指出,pgfmath 本质上实现了这个解析器,它读取看起来像的嵌套函数ln(\x + \y) * sin(\a * mod(\b, 2))
。你的同事可能会被说服
\pgfmathdeclarefunction{band}2{%
\pgfmathparse{#1 * #2}
}
\pgfmathparse{ band(\x, band(1, \y)) }
The answer is \pgfmathresult
答案3
编程语言有其特点:在 TeX 中,您使用大括号而不是圆括号,并且()
如果您想扩展它,平衡嵌套是相当困难的。
带牙套:
\documentclass[a4paper]{article}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\band}{m}
{
\jodb_band:w #1 \q_stop
}
\cs_new:Npn \jodb_band:w #1 , #2 \q_stop
{
\jodb_band:ee { #1 } { #2 }
}
\cs_new:Npn \jodb_band:nn #1 #2
{
\bool_lazy_and:nnTF { \int_compare_p:n { #1 = 1 } } { \int_compare_p:n { #2 = 1 } }
{ 1 }
{ 0 }
}
\cs_generate_variant:Nn \jodb_band:nn { ee }
\ExplSyntaxOff
\begin{document}
0: \band{0,0} % works
0: \band{0,1} % works
0: \band{1,0} % works
0: \band{1,1} % works
1: \band{\band{1,1},1} % works
0: \band{0,\band{1,1}} % works
1: \band{\band{1,1},\band{1,1}} % works
0: \band{\band{0,1},\band{1,1}} % works
\def\x{1}
\def\y{0}
0: \band{\y,\band{\x,\x}} % works
0: \band{\band{\x,\y},\y} % works
0: \band{\band{\y,\y},\band{\y,\y}} % works
1: \band{\band{\x,\x},\band{\x,\x}} % works
\end{document}
顺便说一下,还有一个更简单的方法来完成这项工作:
\documentclass[a4paper]{article}
\usepackage{xfp}
\NewExpandableDocumentCommand{\band}{m}{\fpeval{min(#1)}}
\NewExpandableDocumentCommand{\bor}{m}{\fpeval{max(#1)}}
\begin{document}
and
0: \band{0,0} % works
0: \band{0,1} % works
0: \band{1,0} % works
0: \band{1,1} % works
1: \band{\band{1,1},1} % works
0: \band{0,\band{1,1}} % works
1: \band{\band{1,1},\band{1,1}} % works
0: \band{\band{0,1},\band{1,1}} % works
\def\x{1}
\def\y{0}
0: \band{\y,\band{\x,\x}} % works
0: \band{\band{\x,\y},\y} % works
0: \band{\band{\y,\y},\band{\y,\y}} % works
1: \band{\band{\x,\x},\band{\x,\x}} % works
or
0: \bor{0,0} % works
1: \bor{0,1} % works
1: \bor{1,0} % works
1: \bor{1,1} % works
1: \bor{\bor{1,1},1} % works
1: \bor{0,\bor{1,1}} % works
1: \bor{\bor{1,1},\bor{1,1}} % works
1: \bor{\bor{0,1},\bor{1,1}} % works
%\def\x{1}
%\def\y{0}
1: \bor{\y,\bor{\x,\x}} % works
1: \bor{\bor{\x,\y},\y} % works
0: \bor{\bor{\y,\y},\bor{\y,\y}} % works
1: \bor{\bor{\x,\x},\bor{\x,\x}} % works
\end{document}
min(<number>,<number>)
这是因为fp 表达式中允许使用该语法。
答案4
为了好玩...如何使用 LuaTeX 做到这一点,这完全忽略了您试图提出的编程语言的要点。我使用的是 ConTeXt 语法,但也应该很容易移植到 LaTeX3:
\startluacode
userdata = userdata or {}
userdata.band = function(a,b)
if a == 0 or b == 0 then
return 0
else
return 1
end
end
\stopluacode
\define\band
{\bgroup
% Ideally, should use catcode tables
\catcode`\(=1
\catcode`\)=2
\doband}
\def\doband#1{\ctxlua{local band=userdata.band; context(band(#1))}\egroup}
\starttext
\band(0,0) % works
\band(0,1) % works
\band(1,0) % works
\band(1,1) % works
\band(band(1,1),1)
\band(0,band(1,1))
\stoptext