I'm more than halfway through my twelve-week session here at the Recurse Center. While here, I've been trying to expand my programming horizons beyond my Rails web development, object-oriented centered universe. That has involved exploring natural language processing, hardware hacking, offline-first applications, and silly pure CSS WordArt, to name a few.
Prolog is unlike any language I've ever come across before. It's a declarative rather than procedural language, so instead of programming steps of how something is done, you essentially give it facts and rules, against which it can then execute queries. There are good Prolog tutorials on Dev and elsewhere and I will not attempt to write one here.
It looks something like this:
parent(fantine, cosette). child(X, Y):- parent(Y, X)
The above states "Fantine is Cosette's parent." And establishes that X is the child of Y if Y is the parent of X. We can then run the following queries:
?- parent(fantine, cosette). true ?- child(cosette, fantine). true ?- child(cosette, Who). Who = fantine
In the final example, we are essentially asking "Whose child is Cosette?" to which Prolog supplies a possible value to the variable
Who as a means of solution.
If you'd like to play around more with Prolog in the browser you can do so on this page.
The book went into how this language could be used to coordinate schedules of dolphin trainers and write sudoku solvers, but I was already too focused on my white whale 🐋(pun intended): throwing the perfect dinner party.
So I thought, "What if I could supply my favorite recipes to Prolog in the form of facts and then make a query based on the amount of time I had or items that I had in the pantry?"
I started in on this blueberry muffin recipe.
recipe(muffin). contains(blueberries, muffin). contains(milk, muffin). contains(butter, muffin). contains(eggs, muffin). contains(salt, muffin). contains(sugar, muffin). contains(flour, muffin). contains('baking powder', muffin). diet(vegetarian, muffin). diet(nut-free, muffin). minutes_to_prepare(40, muffin). meal(breakfast, muffin). meal(snack, muffin). meal(dessert, muffin).
I did this for a few more recipes, and soon I was able to build queries like:
?- diet(vegan, First), meal(appetizer, First), meal(dinner, Second), contains_ingredients(Second, [basil, zucchini]), meal(dessert, Third).
Translated to plain English: A vegan appetizer, a dinner that contains basil and zucchini, and a dessert.
Prolog then spits out a menu suggestion:
First = gazpacho, Second = 'summer pasta', Third = muffin
If there is more than one possible menu that satisfies the constraints, you can run it again to see additional options.
This is, of course, a long way from a particularly user-friendly interface, but got me thinking about all the possibilities that could be implemented to make the recipe search tools of my dreams. Here's a gist with the code used here. 🥣🍝🍰