To gain a better understanding of macros, expansion and tex-core in general, I tried to implement foldr
like this:
\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
seems to work fine;
However, foldr
ends up with this error:
Runaway argument?
{\x }\acc \fi ,l,o,, ]\par \end
! File ended while scanning use of \consI.
<inserted text>
\par
I am unsure where this is coming from; I am also unsure where the \fi
is coming from in the error message.
To clear things up: i want empty lists to be [[]]
, [a,[]]
would be a one element list. The invocation of the foldr
function at the end of the file should produce the exact same list that it was given as an argument.
I tried to keep the definition roughly similar to this implementation of an "element based loop"
\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’
}
Maybe there is something wrong with the syntax I want the command to have?
Note that I am aware that this could probably more sensibly be done with latex3 and the sequence data structure; I am interested in solving it using tex only.
EDIT
(code exaples given in haskell notation)
foldr :: (a -> b -> b) -> b -> [a] -> b
foldr f initial b = b
foldr f initial (a:t) = f a (foldr f initial t)
so it is a function that takes a function as an argument,
walks over the given list.
it basically provides the given function f
with an element of the list and an accumulating value acc
(starting out as initial
).
examples:
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"
\ifx
compares{
with the first token in#2
(after argument replacement), so it will usually return false. It would help if you describe what\foldr
is supposed to do. Another problem is that your macros don't work by pure expansion, so they won't behave in\message
.\ifx
part to something (hopefully better); I am still unsure when{}
groups characters to one single parameter and when they are just plain characters. (maybe I understood that wrong in the first place)