The golden language at my current place of work is Python. But we have some pretty gnarly business logic in some places (decision tree of average height 10 and branching factor of maybe 3).

To better understand how all the pieces fit together, I took on the challenge of writing the decision tree out in SWI-Prolog over the weekend, since I figured it would be the most “expressive” way to capture the logic.

I’d taken a PL class in college, and used prolog for a couple weeks therein. But this was the first time I’d used it in years. The first 30 minutes were a struggle, as I tried to remember how predicates worked, and tried to translate my mental model into a series of iteratively applied predicates. But after a couple hours of very satisfying top-down programming, I’d written pretty much the whole thing.

And it worked!

My grand theory is that we’d be able to get compliance, legal, and finance (main stakeholders of the program), to interface with some exposed subset of the predicates, to tweak to their hearts content.

This program could be the Golden source of truth that all implementations would have to live up to. Maybe, we could even hook in python programs to do I/O (fetch inputs from the databases, write decisions to the database), and use this prolog program directly to drive decisions in a python program.

It’s all a fantasy at this point, but it’s a fun one. The idea’s lingered since that weekend, many months ago.

Has anybody pulled off anything similar? Replacing a complex component of a bigger program with a prolog core?

How would you compare your Prolog code to the Python one? Is it more maintainable, was it easier to code, etc.?

I would say it's a qualified yes.

Factually, it is more legible, maintainable, easy to extend. However, imo, this is mostly because all of the I/O had been abstracted away.

In the python program, I/O and logic were interspersed in a way that made it difficult to reason about only one or the other. You have to understand our data models to understand the code, and vice versa.

If I were to rewrite the python program today, it would "look" a lot like the Prolog one, and probably be equally as legible and maintainable.

I think it's an example where Prolog (as a "logic" language) "shepherds" you do the right thing with respect to I/O separation. I imagine if I tried writing it in Haskell or OCaml, the effect would be similar. I'm reminded of this article: https://news.ycombinator.com/item?id=22696229.

Python, meanwhile, is a blank canvas and a full set of paints, which is its great strength in experienced hands, but also its great downfall. When I leave the company, there's nothing stopping another engineer (a junior, or even an experienced engineer with different skill trees) from rewriting things in a way that "works" but compromises legibility or extensibility.

With discipline, you can develop a program in Python that looks quite similar to the Prolog one, but the only guardrails against writing it in spaghetti is psychological.

In any case, it was a fun exercise. It makes me want to try writing more things in different languages, if for no other reason than to improve my usage of the subset of Python I like best. :)

In my experience python gives the best results when you add a little bit of computer science to the mix. It is well within reason to use state machines[0] and constraint programming[1] libraries all from within python, no real need for an extra language.

[0] https://github.com/pytransitions/transitions

[1] https://pypi.org/project/python-constraint

Yep, totally agree. Python's metaprogramming is powerful enough that you can twist it into any shape you like! :)

My favorite gem, especially before python3 and typehinting were more widely in-use, is attrs [0]. It allows you to define rich data types (which python is great for) in a declarative/expressive/legible manner (which python sometimes isn't great for).

imo, it's a fantastic example of how metaprogramming allows libraries to actually enhance a language. Another one that demonstrates the power of MP is fire[1], a tool that allows you to drive classes with a MP-generated CLI.

[0] https://www.attrs.org/en/stable/examples.html [1] https://github.com/google/python-fire