切换代数

切换代数

这是扩展大师的一本书。我试图使用切换代数向同事展示你可以在 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

相关内容