I’ve had a long, difficult week, so I’ve decided to pick something pointlessly
pathological for today. It’s a remarkably goofy language called “Chef”, designed by David Morgan-Mar, in which programs are recipes. Since aside from being a programming language
nutjob, I’m also a pretty good chef, combining two of my favorite things naturally has
some appeal – particularly when done in a pointlessly twisted way.
I said that programs in chef are recipes. I wasn’t joking. The structure of a Chef
program is a recipe title, then an ingredients list, then preparation instructions, and
finally serving information.
The recipe title is the first line of the program. It gives the recipe a name,
which can later be used to call it as a sub-recipe. After the title, you can have
comments – which don’t need to be marked in any way. The real meat of the program
starts with the ingredients.
The ingredients section starts with the keyword “Ingredients.” (period mandatory).
After that, it’s one ingredient per line. Every ingredient must be unique, and every
one must have a numerical quantity. The ingredients are, essentially, your variables.
After the ingredients are a blank line, followed by the keyword “Method.”. Each line after “Method.” is a program statement. All of the things you can do are described in terms of statements that look like recipe steps. Computations are done using mixing bowls, which are basically stacks. A sampling of statements:
-
Put ingredient into nth mixing bowl
- Puts the ingredient on top of the specified bowl.
-
Add ingredient to the nth mixing bowl
- Adds the value of the ingredient to the value on top in the specified bowl.</dd
-
Remove ingredient from nth mixing bowl.
- Subtract the value of the ingredient from the top of the bowl.
-
Fold ingredient into nth mixing bowl.
- remove the value on top of the specified bowl, and store it in ingredient.
-
Combine ingredient with nth mixing bowl.
- Multiplies the top of the bowl by the ingredient.
-
Liquify ingredient
- Convert the specified ingredient to be interpreted as a character rather than an integer.
-
verb ingredient. ... verb until ingredient verbed
- Looping construct. This is basically the same as the BrainFuck looping
construct. If the ingredient named at the loop start is greater than 0, then
the loop is run; if the ingredient named at the loop end is greater than
0, then repeat the loop again. set aside
- Exit from the innermost loop.
-
Pour contents of the nth mixing bowl into the mth baking dish
- Transfer from a mixing bowl to a baking dish. Things in baking
dishes can be printed out at the end of the program. Serve with recipe-name
- Call another recipe as a subroutine. The new recipe will be prepared by
a “sous chef” who gets copies of all of the mixing bowls in use
by the calling chef – but changes to the bowls don’t affect the calling
chef’s bowls. When the sub-recipe complete, the contents of its first bowl
are added to the calling chef’s first bowl. Refrigerate number hours
- Halt execution. If this is a sub-recipe, return to the caller. The number
is optional – if it’s mentioned, then print out the values of the first
number baking dishes.
And so on. These are the basics; there are more instructions in the same vein. For
the complete list, check the Chef
page.
After the main instructions, the program ends with a “Serves
” statement, that says how many portions the recipe produces. The
number
serves statement prints out the content of the first number baking dishes.
So, here’s a nice little hello world recipe. I wouldn’t particularly want to
eat it, but it does the job.
Hello World Souffle. This recipe prints the immortal words "Hello world!", in a basically brute force way. It also makes a lot of food for one person. Ingredients. 72 g haricot beans 101 eggs 108 g lard 111 cups oil 32 zucchinis 119 ml water 114 g red salmon 100 g dijon mustard 33 potatoes Method. Put potatoes into the mixing bowl. Put dijon mustard into the mixing bowl. Put red salmon into the mixing bowl. Put oil into the mixing bowl. Put water into the mixing bowl. Put zucchinis into the mixing bowl. Put oil into the mixing bowl. Put lard into the mixing bowl. Put lard into the mixing bowl. Put eggs into the mixing bowl. Put haricot beans into the mixing bowl. Liquify contents of the mixing bowl. Pour contents of the mixing bowl into the baking dish. Serves 1.
The ingredients are the unicode values of the characters of the hello world
message. As a mnemonic aid, the names of each of the ingredients start with the letter
that their value corresponds to – so “Haricot beans” is the letter “H”. The program dumps all of them into the first mixing bowl. Then the contents of the bowl are liquified (changing them from numbers to characters, and turning the contents bowl
into a string.). Finally, the liquified bowl contents are moved to a baking dish, so
that they can be output, and the “serves” statement outputs the string in the baking
dish. Voila! Hello world.
A much more interesting recipe: generating fibonacci numbers. This gives you more of an idea of just how to do actual computations. Alas, it doesn’t bother to print
them. One of the main weaknesses of Chef is that you can only really output
things when a recipe exits. If you wanted to print the Fibonacci numbers as you
generated them, you’d have to add a sub-recipe to do it.
Fibonacci Al-Dente. This will print the first 20 fibonacci numbers. Ingredients. 1 egg 1 butter 20 carots 1 banana Method. Heat the carots. Put egg into the 1 mixing bowl. Put butter into the 2 mixing bowl. Put carots into the 3 mixing bowl. Liquify the 2 mixing bowl. Clean the 4 mixing bowl. Put egg into the 4 mixing bowl. Add butter to the 4 mixing bowl. Clean the 2 mixing bowl. Pour contents of the 1 mixing bowl into the 2 mixing bowl. Clean the 1 mixing bowl. Pour contents of the 4 mixing bowl into the 1 mixing bowl. Remove banana from 3 mixing bowl. Fold carots into 3 mixing bowl. Fold butter into the 2 mixing bowl. Fold egg into the 1 mixing bowl. Repeat until the carots stink.
It’s a simple program, but cute. Here’s how it works:
- We start with egg=1, butter=1, carots=20, and banana=1.
- “Heat the carrots” starts a loop, which use carots as a loop index.
- Egg, butter, and carots go into separate mixing bowls.
- Then there’s a sort-of elaborate shuffling, which adds the last two
fibonacci numbers together, and rotates contents around so that
we still have the first two fibonacci numbers in egg and butter. (Banana
is just an index used for decrementing carots.) - And repeat until carots=0.
Are you certain you don’t want to use carrots for the Fibonacci Al-Dente?
Mikael:
I didn’t write it 🙂 In most of the pathological programming
posts, I use the language designer’s examples. The only times I do the code myself is when there aren’t enough of the authors’ own examples to demonstrate things. (Like the language a few weeks ago that used a circular queue.) If I’m quoting someone elses code, I don’t feel right changing it.
I believe you need some more lard between your dijon mustard and red salmon.
A really tasty language! Here’s my recommendation for a dessert:
Strawberry Factorial with Whipped Cream.
A delightful dessert, ideal after Fibonacci Al Dente or Ackermann Steak.
Ingredients.
1 kg strawberries
cream
Method.
Take cream from refrigerator.
Put strawberries into mixing bowl.
Whip cream.
Combine cream into mixing bowl.
Scatter cream until desired.
Pour contents of the mixing bowl into baking dish.
Serves 1.
Enjoy!