Building my dream recipe search in Prolog
Tags: prolog, logic, declarativeprogramming, programminglanguages
Published: 2019-07-24 20:19:26

---
title: Building my dream recipe search in Prolog
published: true
description: Exploring the Prolog programming language as a means to throwing the ideal dinner party.
tags: prolog, logic, declarative programming, programming languages
cover_image: https://thepracticaldev.s3.amazonaws.com/i/5c5zz34okouqki8v7cyj.png
---

I'm more than halfway through my twelve-week session here at the [Recurse Center](https://www.recurse.com/). 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](https://dev.to/valeriecodes/exploring-natural-language-processing-with-alice-in-wonderland-ldc), hardware hacking, offline-first applications, and silly pure CSS WordArt, to name a few.

I've been working through the book [7 Languages in 7 Weeks](https://pragprog.com/book/btlang/seven-languages-in-seven-weeks) with a few other folks here, and this week we came upon the [Prolog](https://en.wikipedia.org/wiki/Prolog) programming language.

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](https://dev.to/matchilling/introduction-to-logic-programming-with-prolog-cdh) and [elsewhere](https://www.amzi.com/AdventureInProlog/index.php) and I will not attempt to write one here.

It looks something like this:
```pl
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:

```pl
?- 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](https://swish.swi-prolog.org/).

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](https://cooking.nytimes.com/recipes/2868-jordan-marshs-blueberry-muffins).

```pl
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:
```pl
?- 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:
```pl
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](https://gist.github.com/valeriecodes/7802d297f639d087fe7e624a31951ac8) with the code used here. 🥣🍝🍰