Comment by bux93
2 days ago
The main thing about prolog isn't the algorithms. In fact, the actual depth-first search isn't even part of the standard.
The nice thing about prolog is that you write logical rules, and they can get used in whatever order and direction that is needed. By direction, I mean that if you define "a grandparent is the parent of a parent", you can now use that rule not just to evaluate whether one person is a parent (or to find all grandparents) but also to conclude that if you know someone is a grandparent, and they are the parent of some one, then that person is someone's parent. Ok, it can also do recursion, so if you define an ancestor as a parent or the parent of an ancestor it will recurse all the way up the family tree. Neat.
You could write some kind of runtime that takes c code and brute-forces its way from outputs to inputs, except that regular imperative code allows for all kinds of things that make this impossible (e.g. side-effects). So then, you'd be limited to some subset, essentially ending up with a domain specific language again, albeit with the same syntax as your regular code, rather than those silly :- symbols (although LISP looks much sillier than prolog IMHO).
What the article is getting at is that if you use some features specific to a language, it's hard to embed your code as a library in another language. But is it? I mean, DLLs don't need to be written in the same language, there's stuff like JNI, and famously there's stuff like pytorch and tensorflow that runs CUDA code from python.
> By direction, I mean that if you define "a grandparent is the parent of a parent", you can now use that rule not just to evaluate whether one person is a parent (or to find all grandparents) but also to conclude that if you know someone is a grandparent, and they are the parent of some one, then that person is someone's parent.
Not necessarily.
Could you please expand? Because I have the same state of knowledge of the previous poster. I would like to learn if I'm wrong.
Someone who is a grandparent may also have other children who do not have children.
Debugging rarely works correctly between languages, and features like "find all references" usually break too. Maybe that's not an issue with Prolog because a C logic solver would also be hard to debug, but it's a problem with many template languages.
>The nice thing about prolog is that you write logical rules, and they can get used in whatever order and direction that is needed.
This generalizes!
Prolog: declare relations. Engine figures out how to satisfy them. Bidirectional -- same rules answer "is X a grandparent?" and "find all grandparents."
LLMs do something similar but fuzzier. Declare intent. Model figures out how to satisfy it. No parse -> AST -> evaluate. Just: understand, act.
@tannhaeuser is right that Prolog's power comes from what the engine does -- variables that "range over potential values," WAM optimization, automatic pruning. You can't get that from a library bolted onto an imperative language. The execution model is different.
Same argument applies to LLMs. You can't library your way into semantic understanding. The model IS the execution model. Skills aren't code the LLM runs -- they're context that shapes how it thinks.
Prolog showed that declarative beats imperative for problems where you can formalize the rules. LLMs extend that to problems where you can't.
I've been playing with and testing this: Directories of YAML files as a world model -- The Sims meets TinyMUD -- with the LLM as the inference engine. Seven architectural extensions to Anthropic Skills. 50+ skills. 33 turns of a card game, 10 characters, one LLM call. No round trips. It just works.
https://github.com/SimHacker/moollm/blob/main/designs/stanza...
https://github.com/SimHacker/moollm/tree/main/skills