Not really. I use SWI Prolog for a lot of personal projects (that actually see QPS no less) and there's a lot more to it than that. SWI gives you: good debugging support (with trace and spy), hooks into the Prolog database (with asserta/z and retract), optimized implementations of difference lists, online help, and so much more. Don't even get me started on its amazing DCG support that makes Regex feel like a Neolithic toy. Not only that but Prolog's Syntax gives you very similar properties to lisp's homoiconicity (first class atoms, metaprogramming, etc). Sure you can reimplement all of this in miniKanren, but it's all there waiting for you in SWI Prolog already! There's a lot more to a language than just its concepts.
Every time I hack in Prolog I always feel like I'm living the idea that I "tell the computer what to do not how to do it". It's a shame that more folks don't use it.
Prolog was part of course that I'd taken during my Masters. I loved it then. I would love to take a closer look when I have time ... whenever that happens <sigh> ...
I used it for a graduate course in formal semantics. As our final project, we had to implement Lisp in Prolog and prove the semantics formally. Until that point, I thought I had a good grip on Prolog. Debugging the project nearly drove me nuts! If I had a do-over, I'd learn the SWI debugging tools before attempting it.
I love Prolog and hope to spend more time with it some day. But, the step from Novice to Intermediate is steep.
Thanks. Do you know of any other resources describing Watson's inner workings? ...cause just googling for it leads to one of the zillions of marketing bullshit pages or whitepapers devoid of any real infos that IBM's marketing drones have flooded the web with.
And Prolog is actually an ISO-standardized language so you have a choice of implementations to choose from (for example Yap Prolog, which I found much faster than SWI last I checked, or the highly regarded commercial Sicstus Prolog). Plus, implementing a Prolog engine isn't too much of an effort to do on your own (like I did two times). In fact, there are multiple Prolog implementations for the JVM, for JavaScript, etc.
How can you use DCG in a productive way? If haven't found a good way when there is left recursion. Memonization(tabbling) only sometimes helps and refactoring the grammar into non-left-recursive takes a lot of time and is error prone.
I typically wrap up a left recursive rule as another rule, and then have this rule choose between the base case and the recursive case. This is a pretty standard technique to break down left recursive rules though, and has nothing to do with Prolog, and everything to do with writing parsers.
To complement Karrot_Kream's answer, there's another two things you can do if you're having DCG left-recursion troubles:
The first thing is to use a different parsing strategy. For instance, the Earley parser [1] used to be a typical example of (advanced ish) Prolog and wikipedia says that it performs particularly well with left-recursive languages.
The disadvantage of course is that you're giving up the simplicity of having a built-in grammar-and-parser capability in your language. But in some cases that's probably a very small price to pay.
The other thing you can do, which is in a sense the exact opposite of changing parsers, is to eliminate the possibility of left-recursion from your DCGs by choosing a grammar formalism that precludes it.
It boils down to keeping all your rules looking like this:
P --> [a₁, a₂, ..., aₙ], A₁, A₂, .... Aₘ.
Where each Aᵢ is a terminal or nonterminal and each [aₖ] a terminal.
In other words, expand every nonterminal first to one or more terminals, then any mix of terminals and nonterminals. That way you'll always accept a terminal before expanding a nonterminal and there's no chance of left-recursion.
You can write a short syntax checker to enforce this rule in a post-processing step, or just do it by hand.
You can be a little bit more rigorous and stick to more strict forms, particularly right-regular grammars, or Greibach Normal Form [2], if your grammars are context-free.
Right regular grammars allow a single nonterminal on the right-hand side:
A --> [a], B.
Whereas Greibach Normal Form allows a single terminal followed by any number of nonterminals:
P --> [a], A₁, A₂, .... Aₙ.
The benefit of GNF is that any context-free grammar can be transformed into a grammar in GNF, so you can first write your grammars in a loose form, then convert them to GNF to remove left-recursions. If you want I can probably dig up a reference to how to do the conversion.
Every time I hack in Prolog I always feel like I'm living the idea that I "tell the computer what to do not how to do it". It's a shame that more folks don't use it.