Cooking++

| 5 Comments

We eat three meals a day (or we would, if we woke up early enough for breakfast...). Unless you're Calista Flockhart, you've just gotta eat. You can look at it as a chore, like shaving or teaching the dog that humping visitors' legs is not acceptable behavior unless the visitor is your mother-in-law, but I see it as something to relish. I don't understand why more people don't like to cook. Unlike many other creative passions like gardening, carpentry, and child-rearing, the gratification is almost immediate. Few things are as satisfying as producing a delicious meal.

True chefs don't follow recipes. They coax flavors out of their ingredients through Vulcan mind meld, intuitively knowing that a chilled apple coulis will create a perfect counterpoint to that rutebega. They throw ingredients into the pan by sight-- a dash of this, a handful of that. Measuring spoons are beneath them. Seasoning is an art; the pan, their canvas.

Then there's the rest of us. We need recipes-- codified series of instructions that take us step by step through the creation of a dish. And this morning, in the wake of a couple of fabulously successful new recipes for chicken tikka masala and butter chicken, it hit me that recipes are really just computer programs, with the cook as the central processor.

Just as we declare variables at the top of each program, every recipe begins by declaring its ingredients. Instead of allocating storage in memory, the cook sets aside storage on his countertop or in his mis en place and measures out the appropriate amount of the ingredient. Many recipes present themselves as a series of numbered steps, or subroutines, in the cooking process. The cook proceeds from the top to the bottom, executing each step in turn until he reaches the end. Before running a program/recipe, you have to make sure you meet the hardware requirements. Instead of a blue screen of death when a program crashes, you might get black smoke. You have to clean up what you use, lest the computer/kitchen run out of resources and grind to a halt. And when everything works as intended, the satisfaction is unparalleled. No wonder I love cooking!

Since cooking is just another programming language, recipes can be ported from one system to another. Here's a port of my favorite chocolate chip cookie recipe...

#define COOKIES_PER_BATCH 24;
#define ROWS_PER_SHEET 3;
#define COLUMNS_PER_SHEET 2;
var bowl1, bowl2, platter;
var wet_ingredients[] = { sugar, brown_sugar, melted_butter, milk, vanilla };
var dry_ingredients[] = {flour, baking_soda, salt };
var choc_chips, eggs[2];
var oven;
var baking_sheet[][] = new cookie[ROWS_PER_SHEET][COLUMNS_PER_SHEET];
Main()
{
    oven.Initialize(375);
    AddIngredients(wet_ingredients, ref bowl1);
    bowl1 += egg[0];
    egg[1] -= egg_white;
    bowl1 += egg[1];
    Cooking.Util.Mix(bowl1);
    AddIngredients(dry_ingredients, ref bowl2);
    CombineReceptacles(bowl2, ref bowl1);
    bowl1 += chocolate_chips;
    Cooking.Util.Mix(bowl1);
    bowl1 -= raw_dough / rand(100); // Source of "girlfriend likes raw dough" issue?
    while (bowl1.IsEmpty() == false)
    {
        CreateDropCookies(ref baking_sheet, bowl1);
        BakeCookies(baking_sheet);
        RemoveCookiesFromSheet(baking_sheet, ref platter);
    }
}
AddIngredients(ingredients, ref receptacle)
{
    for (int ing_num = 0; ing_num < ingredients.count; ing_num++)
    {
        receptacle += ingredients[ing_num];
    }
    Cooking.Util.Mix(receptacle);
}
CombineReceptacles(src, ref dest)
{
    // Risk buffer overrun if added all at once.  Workaround: add in 4ths
    for (part = 0; part < 4; part++)
    {
        dest += memcpy(src + sizeof(src / 4), sizeof(src / 4));
        Cooking.Util.Mix(dest);
    }
}
CreateDropCookies(ref baking_sheet, bowl1)
{
    for (row = 0; row < ROWS_PER_SHEET; row++)
    {
        for (column = 0; column < COLUMNS_PER_SHEET; column++)
        {
            if (bowl1.IsEmpty())
            {
                break;
            }
            var doughsize = sizeof(bowl1 / COOKIES_PER_BATCH);
            var doughball = new Doughball(bowl1, doughsize);
            baking_sheet[row][column] = doughball;
            bowl1 -= doughball;
        }
    }
}
BakeCookies(baking_sheet)
{
    oven += baking_sheet;
    System.Util.Delay(840000);  // 14 minutes.  Switch to async timer for multitasking.
    oven -= baking_sheet;
}
RemoveCookiesFromSheet(baking_sheet, platter)
{
    for (row = 0; row < ROWS_PER_SHEET; row++)
    {
        for (column = 0; column < COLUMNS_PER_SHEET; column++)
        {
            if (baking_sheet[row][column] != null)
            {
                platter.Add(baking_sheet[row][column]);
                baking_sheet[row][column] = null;
            }
        }
    }
    platter.Remove(1); // one for the cook!
}

5 Comments

And since one commonly needs to cook more than one dish for a meal, it is good to learn how to execute threaded code.

Also, you should move AddIngredients, CombineReceptacles, etc to a library so you can reuse them in other recipies.

I don't remember ever having to wash things after I wrote a program. Most high level languages clean up the memory used for you, which would be something like doing the dishes in your analogy, I think (except less tedious). Another thing I really dislike about cooking is staying on top of shopping enough that there are fresh and needed ingredients handy - something without analog in the computer world. Deadlines aside, there is almost never a timing element to programming - another thing I find difficult in cooking (especially with more than one thing going on). And finally, if you screw up a program, it's usually a trivial matter to fix it. You certainly would never have to rewrite the whole thing from the begining (including potentially the shopping). It is in these areas that I like coding and loathe cooking, so it doesn't quite work for me.


if (bowl1.IsEmpty()) break; ?


You must go through a lot of baking dishes.

The cookingforengineers.com website has another interesting "port" -- it ports from english (normal recipes) to what I would consider to be graphical representations of trees (mostly binary trees). Come to think of it, this should perhaps not be described as a port, but rather as parsing (the first step in compilation).

Click on one of their recipes and look at the bottom little "table" -- although it looks like a table, it really is a graphical representation of a tree, with the ingredients as "leaf" nodes and the steps/actions as "internal" nodes.

BTW I have never actually tried their recipes. I am a very poor cook. My job at home is garbage collection (incl. cleaning and actual garbage collection) after my wife runs the program.

Monthly Archives