edit: this is known as continuation-passing style. Each recursive call builds its continuation function and passes it along to the next recursive call, to be used as that call chooses (depending on whether it is the base case or not).
Just write down the reduction steps:
repeat_cont 4 "xo" id
repeat_cont 3 "xo" k1 where k1 x = id ("xo" + x)
repeat_cont 2 "xo" k2 where k2 x = k1 ("xo" + x)
repeat_cont 1 "xo" k3 where k3 x = k2 ("xo" + x)
repeat_cont 0 "xo" k4 where k4 x = k3 ("xo" + x)
k4 ""
k3 ("xo" + "")
k2 ("xo" + ("xo" + ""))
k1 ("xo" + ("xo" + ("xo" + "")))
id ("xo" + ("xo" + ("xo" + ("xo" + ""))))
"xoxoxoxo"
Each continuation function ki
is "what to do with the result that will be received from the recursive call".
The recursive case ones, ki
, say "whatever recursive result x
I'm given, prepend s
to it and pass the enlarged string up the chain as the new, modified result".
The outermost one, id
, just says "return the (final) result as is".
When the base case of 0
is reached, k4
continuation function has been built and is ready to receive its argument, to do its job. It will add the "xo"
string to its argument, and pass the result along up the chain of continuation functions, to k3
. The argument will be used in "xo" + x
, so it must be a string.
Adding ""
to a string is an identity operation, so the base case says "just let the chain of continuation functions do their job, without further interference from me".
NB: I've been cautious to always say "continuation function", to avoid confusion with the first-class continuations which are altogether different and much more powerful beasts (not sure if F# has them, though).
res1 "ab"
=>"xoxoxoxoab"
, i.e.res1
represents a string prefix, re: difference-lists. You do show this for ints. Sores2 = (4 +)
andres1 = ("xoxoxoxo" +)
. Nice. – Rockabilly