As an avid Prolog fan, I would have to agree with a lot of Mr. Wayne's comments! There are some things about the language that are now part of the ISO standard that are a bit unergonomic.
On the other hand, you don't have to write Prolog like that! The only shame is that there are 10x more examples (at least) of bad Prolog on the internet than good Prolog.
If you want to see some really beautiful stuff, check out Power of Prolog[1] (which Mr. Wayne courteously links to in his article!)
If you are really wondering why Prolog, the thing about it that makes it special among all languages is metainterpretation. No, seriously, would strongly recommend you check it out[2]
This is all that it takes to write a metainterpreter in Prolog:
I also have a strange obsession with Prolog and Markus Triska's article on meta-interpreters heavily inspired me to write a Prolog-based agent framework with a meta-interpreter at its core [0].
I have to admit that writing Prolog sometimes makes me want to bash my my head against the wall, but sometimes the resulting code has a particular kind of beauty that's hard to explain. Anyways, Opus 4.5 is really good at Prolog, so my head feels much better now :-)
It actually has quite good UX affordances. More than that, however, I find the code imminently hackable, even as someone with very little Prolog experience. Reading through the plwm code really demystified the apparent gap between toy and practical Prolog for me. Heck, even the SWI-Prolog codbase itself is quite approachable!
I'm also mildly surprised at some of OG's gripes. A while back, I ran through Triska's The Power of Prolog[0], which crisply grounds Prolog's mental model and introduces standard conventions. In particular, it covers desugaring syntax into normal predicates, e.g. -/2 as pairs, [,]/2 as special syntax for ./2 cons cells, etc. Apparently, I just serendipitously stumbled into good pedagogical resources!
I'd be interested in ways that people utilize logical programming concepts and techniques into non-LP languages.
I think this article is problematic because Prolog is truly a different paradigm which requires time to understand. Laments about no strings, no functions and "x is confusing" read like expectations of a different paradigm.
Prolog is also unusual in a sense that it is essential to understand what the interpreter does with your code in order to be able to write it well. For vanilla Prolog, that's not so hard. However, when constraint programming and other extensions are added, that becomes much harder to do.
Datalog has the same capabilities as prolog but allows strings right?
My understanding is that they have very different evaluation strategies, bottom up vs top down. But with laziness and pruning you can still achieve the same goals in datalog with more ergonomics, right?
I think every language should have a prolog or datalog implementation, kind of like regex.
It's the other way around. We kind of stumbled on the whole idea of computation thanks to work on First Order Logic, that Prolog borrows its syntax and semantics from.
It's all the other programming languages that have weird syntax, including LISP btw. Prolog's syntax is the quintessential syntax of a formal language for computation.
As to the "data description" part this is just a leaky abstraction almost universally adopted by programming languages, other than LISPs and logic programming languages. In truth, there is no separation between data and computation. And so there is no need for special syntax for either. Prolog is a "data description" language only in the sense that you can describe data and computation in one go.
> ISO "strings" are just atoms or lists of single-character atoms (or lists of integer character codes) [...]. Code written with strings in SWI-Prolog will not work in [other] Prolog.
That's because SWI isn't following ISO (and even moving away from ISO in other places eg. [1]).
ISO Prolog strings are lists of character codes period. It's just that there are convenient string manipulation-like predicates operating on atom names such as sub_atom, atom_concat, atom_length, etc ([2]). You'd use atom_codes to converse between atoms/strings or use appropriate list predicates.
Someone bashing on my pet language? Cracks knuckles
Just kidding. Some of those are stylistic choices I don't have gripes but can understand the criticism. There is however one thing about "Non-cuts are confusing" I'd like to clarify:
In this example:
foo(A, B) :-
\+ (A = B),
A = 1,
B = 2.
It's very obvious why it fails and it has nothing to do with non-cut. Let's say A can be apple and B can be orange and now you're asking Prolog to compare apples to oranges! ;)
In short one has to "hint" Prolog what A and B can be so then it can "figure out" whethever comparison can be made and what is its result. Assuming there exist is_number(X) clause that can instantiate X as a number following would work just fine:
foo(A, B) :-
is_number(A),
is_number(B),
\+ (A = B),
A = 1,
B = 2.
(note that this would be stupid and very slow clause. Instantiation in such clauses like is_number(X) usually starts with some defined bounds. For A = 10000, B = 10001 and lower bound of 1 pessimistic case this clause would require 100M checks!
I think that should be nonvar(A), nonvar(B) because the reason the unification succeeds and \+(A = B) fails is because A and B are variables (when called as foo(A,B). What confuses the author is unification, as far as I can tell.
But, really, that's just not good style. It's bound to fail at some point. It's supposed to be a simple example, but it ends up not being simple at all because the author is confused about what's it supposed to behave like.
> Please just let me end rules with a trailing comma instead of a period, I'm begging you.
The reason Prolog doesn't support trailing commas is exactly the same reason JSON doesn't support trailing commas: the language is designed to be parsed by an operator precedence parser, and the comma is an infix operator.
The fact that Prolog is a purely operator precedence syntax, with a dynamic operator table, allows you to build DSLs embedded in Prolog. CLP(FD) uses this to create the #= operator.
Generally speaking, Prolog syntax is ridiculously simple and uniform. Its pattern matching is the most universal of any programming language partly because of this.
I guess we are supposed to pile on, so I'll add that the author should read "The Art of Prolog" (Sterling & Shapiro) and then "The Craft of Prolog" (O'Keefe).
And also "Prolog Programming for AI" by Bratko and "Programming in Prolog" by Clocksin and Mellish.
Although these days I'd recommend anyone interested in Prolog starts in at the deep end with "Foundations of Logic Programming" by George W. Lloyd, because I've learned the hard way that teaching Prolog as a mere programming language, without explaining the whole logic programming thing, fails.
Re: the comma-at-end-of-line thing: I would sometimes write Prolog like so to avoid that issue:
goal :-
true
, subgoal(A, B)
, subgoal(B, C)
.
This is definitely not standard and I don't know if the WAM optimizes out the gratuitous choice point, but it certainly makes the code easier to work with.
It's not standard but that's how I write Prolog. I thing I got it from SQL?
I don't usually leave the full-stop on its own line though. You can always select the entire line, then move one down to cut it without catching the full stop. If that makes sense?
As someone who is interested in learning more abut these kinds of tools, where does one start? Prolog? datalog? MiniKranren? And now the TFA also introduces Picat.
And once you've settled on one of these, which learning resource should one go with?
Scryer is a good start because it's ISO. Datalog is kind of a subset, MiniKanren is somewhat related but not Prolog, and Picat is kind of Prolog with an imperative language within it.
SWI Prolog is just fine, and you'll find it to be batteries included unlike many other choices. The first thing to learn is the "Prolog state of mind", or how to express your intentions in Prolog without trying to turn it into a functional or imperative programming language.
Prolog will show you another way of thinking. If it does not then you are doing it wrong.
In short, "Here are my gripes about Prolog, a language that I don't understand."
It's perfectly fine to not like Prolog, but I do feel that if you're going to write an article about why you don't like it, you should at least spend some time figuring it out first.
He says of the cut operator "This is necessary for optimization but can lead to invalid programs." Imagine if a programmer new to C++ said the same thing of the "break" keyword. That's how ridiculous it sounds. Yes, cut can be used to prune backtracking and eliminate unneeded work, but that's hardly it's purpose. It leads to "invalid" programs (by which I assume he means, programs that do something other than what he wants) only in cases where you are using it wrong. Cut is no more "necessary for optimization" than break is. It's a control structure that you don't understand
Negation (\+) is confusing, and the author correctly provides examples where its meaning is unintuitive when applied to unbound variables. That's because it's not strictly speaking a negation predicate, but rather a "not provable" predicate. In that light, the examples in the article make perfect sense. Yes, Prolog is a programming language, so the order of terms matter, even if the order wouldn't matter in pure logic.
Look, Prolog is a weird language. It has a learning curve. It's not "just another language" in the Java, C++, Pascal, Python mold. I get it. But this article has the flavor of an impatient newbie getting frustrated because he can't be bothered to read the documentation.
> In short, "Here are my gripes about Prolog, a language that I don't understand."
> this article has the flavor of an impatient newbie getting frustrated because he can't be bothered to read the documentation.
The author has written about Prolog in a positive light before (and linked to it in the post), I don't get the impression that these are all "the author doesn't understand what they're doing".
Their first complaint, that "strings are not standardised, so code working with strings in SWI-Prolog is not compatible with Scryer Prolog", seems an appropriate thing to be unhappy about (unless the author is just wrong?).
Your response to their gripe about \+ being "not provable" instead of "negation" notes it's a subtle difference, and that Prolog differs from pure logic there.
The author even notes that doing due diligence, they found a solution to a complaint they had. This doesn't strike me as "can't be bothered to read the documentation".
I, too, am a big fan of prolog and have (at least) yearly binges where I write a lot of it for fun and profit (and some frustration), but I do not consider myself to be an expert. But even I can see that the author has what I would consider a pretty basic understanding of prolog. Which makes it even more surprising they are writing a book that uses prolog.
Yeah, exactly why I'm not writing the same sort of article about Haskell or prolog. I'm inexperienced in both and the effort to learn them was more than I wanted to spend.
I'm wildly out of my depth here, but sometimes I find I learn quickly if I try out my intuition publicly and fail spectacularly :)
> "This is necessary for optimization but can lead to invalid programs."
Is this not the case? It feels right in my head, but I assume I'm missing something.
My understanding:
- Backtracking gets used to find other possible solutions
- Cut stops backtracking early which means you might miss valid solutions
- Cut is often useful to prune search branches you know are a waste of time but Prolog doesn't
- But if you're wrong you might cut a branch with solutions you would have wanted and if Prolog iterates all other solutions then I guess you could say it's provided an invalid solution/program?
Again, please be gentle. This sounded reasonable to me and I'm trying to understand why it wouldn't be. It's totally possible that it feels reasonable because it might be a common misconception I've seen other places. My understanding of how Prolog actually works under-the-hood is very patchy.
Prolog is pretty unique. I’ve run into similar frustrations when I have used it as well. I think you have to drop all your preconceived notions and past programming experience when you use Prolog and just accept it as it is. Prolog was developed to run in very small machines and so the resolution algorithm operates in a strict order. This means clause order sometimes matters. Overall, I’ve found it useful to always keep in mind that I’m unifying trees of terms, not so much programming in a pure logical language.
Anyone have experience with the author's book? I am just getting into this world right now, as it happens, and am working on Art of Prolog, Simply Logical, and the Reasoned Schemer, but other suggestions for resources that are particularly good would be welcome!
I'll warn you that Picat is very much a "research language" and a lot of the affordances you'd expect with a polished PL just aren't there yet. There's also this really great "field notes" repo from another person who learned it: https://github.com/dsagman/picat
[+] [-] upghost|2 months ago|reply
Prolog: "Mistakes were made"
As an avid Prolog fan, I would have to agree with a lot of Mr. Wayne's comments! There are some things about the language that are now part of the ISO standard that are a bit unergonomic.
On the other hand, you don't have to write Prolog like that! The only shame is that there are 10x more examples (at least) of bad Prolog on the internet than good Prolog.
If you want to see some really beautiful stuff, check out Power of Prolog[1] (which Mr. Wayne courteously links to in his article!)
If you are really wondering why Prolog, the thing about it that makes it special among all languages is metainterpretation. No, seriously, would strongly recommend you check it out[2]
This is all that it takes to write a metainterpreter in Prolog:
Writing your own Prolog-like language in Prolog is nearly as fundamental as for-loops in other language.[1] https://www.youtube.com/@ThePowerOfProlog
https://www.metalevel.at/prolog
[2] https://www.youtube.com/watch?v=nmBkU-l1zyc
https://www.metalevel.at/acomip/
[+] [-] schmuhblaster|2 months ago|reply
I have to admit that writing Prolog sometimes makes me want to bash my my head against the wall, but sometimes the resulting code has a particular kind of beauty that's hard to explain. Anyways, Opus 4.5 is really good at Prolog, so my head feels much better now :-)
[0] http://github.com/deepclause/deepclause-desktop
[+] [-] goku12|2 months ago|reply
[+] [-] xelxebar|2 months ago|reply
https://github.com/Seeker04/plwm
It actually has quite good UX affordances. More than that, however, I find the code imminently hackable, even as someone with very little Prolog experience. Reading through the plwm code really demystified the apparent gap between toy and practical Prolog for me. Heck, even the SWI-Prolog codbase itself is quite approachable!
I'm also mildly surprised at some of OG's gripes. A while back, I ran through Triska's The Power of Prolog[0], which crisply grounds Prolog's mental model and introduces standard conventions. In particular, it covers desugaring syntax into normal predicates, e.g. -/2 as pairs, [,]/2 as special syntax for ./2 cons cells, etc. Apparently, I just serendipitously stumbled into good pedagogical resources!
I'd be interested in ways that people utilize logical programming concepts and techniques into non-LP languages.
[0]:https://www.metalevel.at/prolog
[+] [-] usgroup|2 months ago|reply
Prolog is also unusual in a sense that it is essential to understand what the interpreter does with your code in order to be able to write it well. For vanilla Prolog, that's not so hard. However, when constraint programming and other extensions are added, that becomes much harder to do.
[+] [-] pjmlp|2 months ago|reply
There were only two prevalent attitudes, some of us really loved FP (me included), others hated it and could hardly wait to get it done.
Somehow there was a similar overlap with those of us that enjoyed going out of mainstream languages, and those that rather stay with Pascal and C.
[+] [-] aeonik|2 months ago|reply
My understanding is that they have very different evaluation strategies, bottom up vs top down. But with laziness and pruning you can still achieve the same goals in datalog with more ergonomics, right?
I think every language should have a prolog or datalog implementation, kind of like regex.
[+] [-] rramadass|2 months ago|reply
> Prolog is also unusual in a sense that it is essential to understand what the interpreter does with your code in order to be able to write it well.
100% this!
Coming from procedural/OO paradigms i did not understand how to think about Prolog until i read Robert Kowalski's paper Predicate Logic as a Programming Language - https://www.researchgate.net/publication/221330242_Predicate...
I still have a long way to go but at least i am on the right track.
[+] [-] gota|2 months ago|reply
They are necessary in practice, though. But boy do a cut here and there makes it harder for catching up to some Prolog codebase.
[+] [-] infotainment|2 months ago|reply
To me, it feels like a data description language that someone discovered could be tricked into performing computation.
[+] [-] hwayne|2 months ago|reply
[+] [-] YeGoblynQueenne|2 months ago|reply
It's all the other programming languages that have weird syntax, including LISP btw. Prolog's syntax is the quintessential syntax of a formal language for computation.
As to the "data description" part this is just a leaky abstraction almost universally adopted by programming languages, other than LISPs and logic programming languages. In truth, there is no separation between data and computation. And so there is no need for special syntax for either. Prolog is a "data description" language only in the sense that you can describe data and computation in one go.
[+] [-] jjgreen|2 months ago|reply
[+] [-] tannhaeuser|2 months ago|reply
> ISO "strings" are just atoms or lists of single-character atoms (or lists of integer character codes) [...]. Code written with strings in SWI-Prolog will not work in [other] Prolog.
That's because SWI isn't following ISO (and even moving away from ISO in other places eg. [1]).
ISO Prolog strings are lists of character codes period. It's just that there are convenient string manipulation-like predicates operating on atom names such as sub_atom, atom_concat, atom_length, etc ([2]). You'd use atom_codes to converse between atoms/strings or use appropriate list predicates.
[1]: https://www.reddit.com/r/prolog/comments/1089peh/can_someone...
[2]: https://quantumprolog.sgml.net/docs/libreference.html#string...
[+] [-] YeGoblynQueenne|2 months ago|reply
... we've disagreed about this before though :)
[+] [-] xlii|2 months ago|reply
Just kidding. Some of those are stylistic choices I don't have gripes but can understand the criticism. There is however one thing about "Non-cuts are confusing" I'd like to clarify:
In this example:
It's very obvious why it fails and it has nothing to do with non-cut. Let's say A can be apple and B can be orange and now you're asking Prolog to compare apples to oranges! ;)In short one has to "hint" Prolog what A and B can be so then it can "figure out" whethever comparison can be made and what is its result. Assuming there exist is_number(X) clause that can instantiate X as a number following would work just fine:
(note that this would be stupid and very slow clause. Instantiation in such clauses like is_number(X) usually starts with some defined bounds. For A = 10000, B = 10001 and lower bound of 1 pessimistic case this clause would require 100M checks![+] [-] YeGoblynQueenne|2 months ago|reply
But, really, that's just not good style. It's bound to fail at some point. It's supposed to be a simple example, but it ends up not being simple at all because the author is confused about what's it supposed to behave like.
[+] [-] cbarrick|2 months ago|reply
The reason Prolog doesn't support trailing commas is exactly the same reason JSON doesn't support trailing commas: the language is designed to be parsed by an operator precedence parser, and the comma is an infix operator.
The fact that Prolog is a purely operator precedence syntax, with a dynamic operator table, allows you to build DSLs embedded in Prolog. CLP(FD) uses this to create the #= operator.
[+] [-] usgroup|2 months ago|reply
[+] [-] floxy|2 months ago|reply
[+] [-] YeGoblynQueenne|2 months ago|reply
Although these days I'd recommend anyone interested in Prolog starts in at the deep end with "Foundations of Logic Programming" by George W. Lloyd, because I've learned the hard way that teaching Prolog as a mere programming language, without explaining the whole logic programming thing, fails.
[+] [-] subjectsigma|2 months ago|reply
[+] [-] YeGoblynQueenne|2 months ago|reply
I don't usually leave the full-stop on its own line though. You can always select the entire line, then move one down to cut it without catching the full stop. If that makes sense?
[+] [-] cyberpunk|2 months ago|reply
[+] [-] wodenokoto|2 months ago|reply
And once you've settled on one of these, which learning resource should one go with?
[+] [-] cess11|2 months ago|reply
Scryer is a good start because it's ISO. Datalog is kind of a subset, MiniKanren is somewhat related but not Prolog, and Picat is kind of Prolog with an imperative language within it.
[+] [-] rramadass|2 months ago|reply
Then checkout the books recommended by user "YeGoblynQueenne" who knows this domain pretty well.
[+] [-] usgroup|2 months ago|reply
Prolog will show you another way of thinking. If it does not then you are doing it wrong.
[+] [-] egl2020|2 months ago|reply
[+] [-] hackyhacky|2 months ago|reply
It's perfectly fine to not like Prolog, but I do feel that if you're going to write an article about why you don't like it, you should at least spend some time figuring it out first.
He says of the cut operator "This is necessary for optimization but can lead to invalid programs." Imagine if a programmer new to C++ said the same thing of the "break" keyword. That's how ridiculous it sounds. Yes, cut can be used to prune backtracking and eliminate unneeded work, but that's hardly it's purpose. It leads to "invalid" programs (by which I assume he means, programs that do something other than what he wants) only in cases where you are using it wrong. Cut is no more "necessary for optimization" than break is. It's a control structure that you don't understand
Negation (\+) is confusing, and the author correctly provides examples where its meaning is unintuitive when applied to unbound variables. That's because it's not strictly speaking a negation predicate, but rather a "not provable" predicate. In that light, the examples in the article make perfect sense. Yes, Prolog is a programming language, so the order of terms matter, even if the order wouldn't matter in pure logic.
Look, Prolog is a weird language. It has a learning curve. It's not "just another language" in the Java, C++, Pascal, Python mold. I get it. But this article has the flavor of an impatient newbie getting frustrated because he can't be bothered to read the documentation.
[+] [-] dwattttt|2 months ago|reply
> this article has the flavor of an impatient newbie getting frustrated because he can't be bothered to read the documentation.
The author has written about Prolog in a positive light before (and linked to it in the post), I don't get the impression that these are all "the author doesn't understand what they're doing".
Their first complaint, that "strings are not standardised, so code working with strings in SWI-Prolog is not compatible with Scryer Prolog", seems an appropriate thing to be unhappy about (unless the author is just wrong?).
Your response to their gripe about \+ being "not provable" instead of "negation" notes it's a subtle difference, and that Prolog differs from pure logic there.
The author even notes that doing due diligence, they found a solution to a complaint they had. This doesn't strike me as "can't be bothered to read the documentation".
[+] [-] IceDane|2 months ago|reply
I, too, am a big fan of prolog and have (at least) yearly binges where I write a lot of it for fun and profit (and some frustration), but I do not consider myself to be an expert. But even I can see that the author has what I would consider a pretty basic understanding of prolog. Which makes it even more surprising they are writing a book that uses prolog.
[+] [-] cogman10|2 months ago|reply
[+] [-] doorhammer|2 months ago|reply
> "This is necessary for optimization but can lead to invalid programs."
Is this not the case? It feels right in my head, but I assume I'm missing something.
My understanding: - Backtracking gets used to find other possible solutions - Cut stops backtracking early which means you might miss valid solutions - Cut is often useful to prune search branches you know are a waste of time but Prolog doesn't - But if you're wrong you might cut a branch with solutions you would have wanted and if Prolog iterates all other solutions then I guess you could say it's provided an invalid solution/program?
Again, please be gentle. This sounded reasonable to me and I'm trying to understand why it wouldn't be. It's totally possible that it feels reasonable because it might be a common misconception I've seen other places. My understanding of how Prolog actually works under-the-hood is very patchy.
[+] [-] drob518|2 months ago|reply
[+] [-] unknown|2 months ago|reply
[deleted]
[+] [-] iainctduncan|2 months ago|reply
[+] [-] usgroup|2 months ago|reply
[+] [-] fithisux|2 months ago|reply
Picat (mentioned by the author) Datalog Mercury XSB
are there more?
[+] [-] usgroup|2 months ago|reply
I think Curry is an interesting take on logic programming. A sort of Haskell meets Prolog.
[+] [-] doorhammer|2 months ago|reply
Bidirectionality has always been super fascinating.
Didn’t know about Picat. 100% going to check it out.
[+] [-] hwayne|2 months ago|reply
[+] [-] shawn_w|2 months ago|reply
[+] [-] mcswell|2 months ago|reply
thisWouldBeGreat: !, fail.
[+] [-] bw86|2 months ago|reply
[+] [-] unknown|2 months ago|reply
[deleted]