function of the day: fold

The fold function does very much what the name implies: it’s meant to fold ingredients into a big mixing bowl, of course. Here’s a definition:


;; 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)
(cond
[(empty? ingredients) a-bowl]
[else
(local ((define mixed-bowl (folding-action
(first ingredients)
a-bowl)))
(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.
(define (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:


(local
((define (whisk an-ingredient a-bowl)
(cond [(string=? an-ingredient "eggs")
(string-append a-bowl "egg-white-only")]
[else
(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))
15

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.

death and taxes

I can’t help feeling haunted about the deaths in yesterday’s shooting. The shooting itself makes no sense to me.

I can appreciate that people are trying to find meaning in the murderer’s actions, trying to blame video games, or psychotic drugs, or jealousy, or divine retribution. It can’t all be random, can it?

I suppose there’s a story about the murderer that remains to be told, the motives and the exposure of lurid, petty details. Still, he is meaningless to me.

I do see clear meaning in the actions of people like Liviu Librescu. How gloriously different are the saints. I’d rather think about Professor Librescu and the others like him, who faced death with courage, teaching one final lesson: “Love is stronger than death.” Another one of those lessons that I’m trying to believe.

stick a fork() in it

Sometimes I really really dislike C for its low-levelness.

Here’s one concrete example why. Predict the output of the following program:


#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char** argv) {
printf("hello world\n");
if (fork() == 0) {
printf("child\n");
} else {
printf("parent\n");
}
return 0;
}

with the following:


dyoo@dyoo-desktop:~/work/net-2$ gcc -Wall test-fork.c
dyoo@dyoo-desktop:~/work/net-2$ ./a.out
[predict your output here #1]
dyoo@dyoo-desktop:~/work/net-2$ ./a.out | cat
[predict your output here #2]

Yes; I was surprised too, but #1 and #2 can produce different output.

At least, this is what I see:


dyoo@dyoo-desktop:~/work/net-2$ ./a.out
hello world
child
parent
dyoo@dyoo-desktop:~/work/net-2$ ./a.out | cat
hello world
child
hello world
parent

The bug here is the interaction between the low-level fork() and the way that buffered output works in C. In the second case, since I’m piping through cat, there’s more output buffering going on. The first printf() is buffered and not immediately printed but rather stored somewhere. The fork() duplicates the process. So when both the child and parent processes close, they flush their respective buffers… and we see this unusual output.

Some man pages do talk about this, like the one from SGI IRIX. Linux’s man pages, not so much. Ah well.

cyberdyne

I went to the NEPLS conference at Tufts University on Wednesday. It was a lot of fun; I got to hear programming language theory talks and meet with other people interested in the same sort of crazy things that pull my attention. I did like Dave‘s talk: the idea of collapsing idempotent type checks to preserve space seemed perfectly reasonable. I wonder if any of that will trickle back into PLT’s contract system.

The last presentation, on Spatial Computing, was especially fascinating. At a first glance, it seemed ridiculous, and the scope of the project so breathtakingly absurd. I clamped my hands over my mouth to muffle my giggles. But as the speaker presented more and more, the whimsical thought came into to me: maybe this is how Skynet begins.

I hope that I too will someday build something that brings both laughter and pondering thoughts. And I’ll also keep in mind to try avoiding the development of systems that might lead to the creation of bloodthirsty androids.