Prolog in Ruby
About a month ago, I began experimenting with Prolog. (If you’re a Mac user wanting to tinker with Prolog, I’d recommend SWI-Prolog. I couldn’t get any other prolog implementation to build or run on my MacBook Pro.) I’m certainly not an expert now, and I’m not leaving Ruby for Prolog, but I did learn enough to appreciate the power of logic programming. (Curiously, I found that logic programming is very similar to functional programming in some respects.)
How timely, then, was Mauricio Fernandez’s article today about Logic Programming in Ruby.
It is cool stuff, to be sure! Prolog, in Ruby. You could just drop Mauricio’s library into your app and have a logic engine available for you, using a Prolog-esque DSL. (A previous article on a similar topic, but which only described a possible DSL, is here.)
That Prolog DSL in Ruby is an excellent first step. It opens all kinds of doors. The next step, I think, is a way to do logic programming in Ruby, using a Rubyish syntax. Prolog is nice and all, and its syntax (intentionally) mirrors the mathematic syntax of formal logic, but admit it: unless you’re familiar with that formal syntax, the meaning of a Prolog program is about as transparent as a two-year-old Perl program. Consider the following example from Mauricio’s article:
1 2 3 4 5 6 7 8 9 10 11 |
sibling[:X,:Y] <<= [ parent[:Z,:X], parent[:Z,:Y], noteq[:X,:Y] ] parent[:X,:Y] <<= father[:X,:Y] parent[:X,:Y] <<= mother[:X,:Y] father["matz", "Ruby"].fact mother["Trude", "Sally"].fact father["Tom", "Sally"].fact father["Tom", "Erica"].fact father["Mike", "Tom"].fact query sibling[:X, "Sally"] |
Wouldn’t it be cool if you could define that with something closer to natural language? (Natural language, I know, introduces all kinds of ambiguities, which is why mathematicians use a more rigorous formal language for describing things like logic, but just follow along for a minute.) The following has not been implemented (at least by me), but wouldn’t it be nifty if it worked?
1 2 3 4 5 6 7 8 9 10 11 12 13 |
:X.sibling_of(:Y).if :Z.parent_of(:X).and(:Z.parent_of(:Y)).and(:X.noteq(:Y)) :X.parent_of(:Y).if :X.father_of(:Y) :X.parent_of(:Y).if :X.mother_of(:Y) "matz".father_of "Ruby" "Trude".mother_of "Sally" "Tom".father_of "Sally" "Tom".father_of "Erica" "Mike".father_of "Tom" # returns an Enumerable of the possible solutions result = :X.sibling_of("Sally").solutions result.each { |solution| p solution } |
Maybe that’s too verbose, or too much syntax. I’m sure it’s a little naive. (the Towers of Hanoi example, for instance, is hard to convert to this kind of syntax.) It’s pretty much off the top of my head, and could no doubt be made better. Nevertheless, I think it reads more naturally than Prolog, and feels more like Ruby.
Perhaps I’ll tinker on this…I’ve got at least one side project that could use a logic engine, and I’d love to use one with a clean, Ruby-esque syntax. If anyone beats me to the punch, though, I won’t be disappointed.
Reader Comments
In 1996 I had a Prolog CS1 course when at university. At first it seemed a quite unusual language to me, but when you get used to not having any arms or legs programming wise it’s actually very powerful.
Let me recommend Clocksin and Mellish as an excellent literary source on the subject.
http://www.amazon.com/Programming-in-PROLOG-F-Clocksin/dp/3540583505
28 Oct 2006
We learnt Prolog in an AI class, but beyond hapless attempts at generating AI, can someone remind me what else Logic Programming can do? Where would I write logic syntax instead of normal procedural syntax and be happy about it?
Nic
29 Oct 2006
Forget that – read the rest of the eigenclass article and there are examples at the bottom.
29 Oct 2006
Hi all,
I implemented a Prolog in Smalltalk (called Soul, with some extras that I will not dwell about here, but that have to do with integrating Prolog and Smalltalk). So I wanted to chime in with a number of examples that we have been doing with an integration of a logic language and a reflective object-oriented one.
This is fun to do what we call ‘Logic Meta Programming’ : you can do logic queries on source code, which can be quite a lot shorter than doing the same via your language’s built-in introspection primitives (especially if you need forms of backtracking support). We used this to implement all kinds of structural verification queries (e.g. find me all classes that implement a visitor design pattern), architectural checks (give me all classes from this layer that reference classes from the layer below), aspect-oriented programming (using the logic language to express pointcuts or using it to do the actual weaving – composition of code), etc.
Oh, yes, a fellow named Kris Gybels has done very interesting linguistic integration of Prolog and OO languages. It’s not trivial to come up with a good syntactic integration where you can transparantly pass values from one of the two paradigms to the other, without jumping through hoops (like through using an API). We have lots of ideas and implementations of various forms of symbiosis, so if you are interested in this, we will happily tell you the various things we tried.
If you want more info on any of these, just drop me a mail ([email protected]) and I’ll happily respond. Or Google and start reading all kinds of research articles ;-)
And consider writing a research paper for the Dnamic Languages Symposium or the IEEE Special Issue on Rapid Prototyping with Dynamically Typed Languages.
30 Oct 2006
As he points out near the top of his blog entry, the tiny_prolog.rb library is not Mauricio’s – he picked it up from a couple of Japanese articles. The links are near the top of his blog entry,
http://www.okisoft.co.jp/esc/prolog/in-ruby.html http://codezine.jp/a/article.aspx?aid=461
Babelfish can render these into semi-understandable “all-your-base-are-belong-to-us”-like English, if you want to try to read them. It can’t do anything with the author’s name, unfortunately, so I still don’t know who to credit with this work. The syntax used in the original work is somewhat more Rubyish than Mauricio’s.
31 Oct 2006
TomP, thanks for pointing that out. It’s true that the lion’s share of the work was by the Japanese author, and Mauricio then added some sugar on top.
31 Oct 2006