;; fold: (ingredient bowl -> bowl) bowl (listof ingredient) -> bowl
;; Folds in a list of ingredients into a bowl with a folding-action.
(define (fold folding-action a-bowl ingredients)
[(empty? ingredients) a-bowl]
(local ((define mixed-bowl (folding-action
(fold folding-action mixed-bowl (rest ingredients)))]))
FOLD here adds an ingredient at a time, using the folding-action to mix in every ingredient thoroughly into our large bowl. Once we have this incorporating function, we can roll up our sleeves and whisk some pancake batter:
;; make-pancake-batter: -> string
;; Example of FOLD to make pancake batter.
(local ((define (whisk an-ingredient a-bowl)
(string-append a-bowl an-ingredient))
(define pancake-ingredients '("flour" "sugar" "eggs" "milk"))
(define empty-bowl ""))
(fold whisk empty-bowl pancake-ingredients)))
Oh! I forgot the baking powder, so those pancakes will be a little stiff. Oh well.
Of course, we might even want to whisk in a slightly different way:
((define (whisk an-ingredient a-bowl)
(cond [(string=? an-ingredient "eggs")
(string-append a-bowl "egg-white-only")]
(string-append a-bowl an-ingredient)])))
(fold whisk "" '("flour" "eggs" "cabbage")))
Now we've got the basics of an okonomiyaki, I suppose.
We might even be silly enough to mix things that aren't even food!
> (fold + 0 '(1 2 3 4 5))
but this seems like a boring example compared to whisking.
Folding is popular, but for some reason it goes by different names by different programming camps. Python programmers call it REDUCE, and Ruby programmers call it INJECT. I don't know about these names, though: I think they sound a little bit aggressive for my taste. As for me, I like the homeliness of "fold": it reminds me of the kitchen.