为了更好地理解宏、扩展和 tex-core,我尝试foldr
如下方式实现:
\long\def\cons#1#2{%
\def\tmp{#2}%
\ifx\tmp\nil%
[#1,[]]%
\else
\consI{#1}#2%
\fi
}%
\long\def\consI #1[#2]{%
[#1,#2]%
}%
\def\nil{[]}%
\long\def\foldr(λ#1,#2->#3)#4[#5]{%
\def\tempitem{#5}%
\ifx\tempitem\nil%
\def\next{#4}%
\else
\def\next{%
\foldrI(λ#1,#2->#3)<#4>#5 %
}%
\fi
\next
}%
\long\def\foldrI(λ#1,#2->#3)<#4>#5,#6{%
\def#1{#5}%
\def#2{\foldr(λ#1,#2->#3)#4[#6]}%
#3 %
}%
\cons{4}{[3,[]]}\par
\foldr(λ\x,\acc->\cons\x\acc){\nil}[h,e,l,l,o,[]]\par
\end
cons
似乎工作正常;但是,foldr
最终出现此错误:
Runaway argument?
{\x }\acc \fi ,l,o,, ]\par \end
! File ended while scanning use of \consI.
<inserted text>
\par
我不确定这是从哪里来的;我也不确定\fi
错误消息是从哪里来的。
为了澄清一下:我希望空列表是[[]]
,它将是一个元素列表。在文件末尾[a,[]]
调用该函数应该生成与作为参数给出的列表完全相同的列表。foldr
我试图使该定义与“基于元素的循环”的实现大致相似
\def\listingloopENDMARKER{\par \listingloopENDMARKER}
\long\def\listingloop#1in#2#3{%
\looppicker{#1}{#3}#2,\listingloopENDMARKER,%
}%
\long\def\looppicker#1#2#3,{%
\def\tempitem{#3}%
\ifx\tempitem\listingloopENDMARKER
\let\next=\relax%
\else
\def#1{#3}%
#2%
\def\next{\looppicker{#1}{#2}}%
\fi
\next
}%
\listingloop\x in{a,b,c,,d,e}{%
The current item is ‘\x’
}
也许我想要的命令的语法有问题?
请注意,我知道使用 latex3 和序列数据结构可能更合理地完成此操作;我感兴趣的是仅使用 tex 来解决它。
编辑
(以 Haskell 符号给出的代码示例)
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f initial b = b
foldr f initial (a:t) = f a (foldr f initial t)
所以它是一个以函数作为参数的函数,遍历给定的列表。它基本上为给定的函数提供了f
列表的一个元素和一个累积值acc
(从开始initial
)。
例子:
foldr (+) 0 [1,2,3] == 0+3+2+1
foldr (\x acc -> cons x acc) [] [1,2,3] == [1,2,3]
foldr (\x acc -> cons (x+1) acc) [] [1,2,3] == map (+1) [1,2,3] == [2,3,4]
foldr (\x acc -> "_" ++ x ++ acc) "" ["hi","this","is"] == "_hi_this_is"
答案1
在
\foldr(λ\x,\acc->\cons\x\acc){\nil}[h,e,l,l,o,[]]
#5
是h,e,l,l,o,[
(终止于第一个]
)
你需要
\foldr(λ\x,\acc->\cons\x\acc){\nil}[{h,e,l,l,o,[]}]
但是由于您总是需要使用括号组来保护嵌套,[]
因此最好使用{..}
与[...]
列表构造不同的语法。