这个版本的 foldr 有什么问题?

这个版本的 foldr 有什么问题?

为了更好地理解宏、扩展和 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,[]]

#5h,e,l,l,o,[(终止于第一个]

你需要

 \foldr(λ\x,\acc->\cons\x\acc){\nil}[{h,e,l,l,o,[]}]

但是由于您总是需要使用括号组来保护嵌套,[]因此最好使用{..}[...]列表构造不同的语法。

相关内容