The Prolog Story
kylecordes.com
kylecordes.com
Prolog is awesome for some types of problems like graph operations, ad-hoc rule systems, planning, etc.
If you want to play/learn, I would recommend Swi-Prolog. Jan Wielemaker does a great job writing and maintaining Swi-Prolog. The semantic web libraries and other Swi-Prolog libraries are very good stuff!
I have been searching for new work opportunities that would involve more freedom in programming language choice (specifically allowing me, as the developer, to explore tools like Prolog, Lisp, and Ruby as appropriate). Sadly, this has been somewhat fruitless in my geographic region. There is a (probably well-founded) desire on the part of companies to use what we can refer to as "lowest common denominator" tools (Java, C#, Oracle, MS SQL Server) with the occasional upstart using Ruby/Rails. When I say LCD tools, I don't mean to denigrate those languages/platforms, merely point out that companies seem more comfortable knowing that there is a large pool of potential programmers available with those skills.
PG has weighed in on the side of starting your own company and using more powerful languages as a competitive advantage (the whole blub/magic of Lisp set of essays). It seems that few companies see programming language as competitive advantage or (based on your comment) be interested in hiring consultants such as yourself to implement higher level software that leverages these uncommon languages.
I'm curious - have you had projects where you felt that Prolog or Lisp represented a "better" choice than Java or Ruby but had customer requirements that specified language choice upfront? Have you "pitched" Prolog or Lisp to customers, maybe saying something like "ah, using Prolog here would require only 20 hours of my dev/consultant time, but using Java will require an 80 hour solution"?
I'm quite interested in using Prolog, Scheme, or Lisp at the "day job" so hearing any of your thoughts might help better prepare my own internal pitches . . .
If you want to work in a particular language such as Common Lisp I suggest writing a useful open source project and that could lead to work in Lisp, and at the least you will learn something and have fun.
I think that this is valid for most projects in any language.
Added benefit: When it is time to start coding, you can amaze your coworkers by brain dumping a decently coded solution at typing speed.
Sitting there with a notepad and a pencil thinking about the problem is when I find I actually solve the difficult problems not when I type furiously at a keyboard.
One day myself and another guy were debugging a piece of code by staring at it, figuring the logic out in our heads and pitching theories back and forward. The boss walked past, saw we were sitting there "doing nothing" and told us to do some work... ugh!
"Declarative programming clears the mind." - Sterling & Shapiro, _The Art of Prolog_
Provided you don't abuse the cut operator, a Prolog program will consist of a series of rules which each have a logical meaning in isolation. Reasoning about Prolog code is so different from trying to unravel what's actually happening with several layers of OO polymorphic dispatch, it's not even funny.
"Elegance is not optional." - Richard O'Keefe, _The Craft of Prolog_
Where you're dynamically building up facts and clauses, and you need more general solving logic at run time, then I think Prolog is more warranted. But that's a smaller niche, IMO.
Consider that we know, and have known for some time, proper ways to manage dynamic memory. We still consider doing it correctly in practice not trivial and consider automatic garbage collection a productivity win.
This does indeed annoy people who put a lot of work into building complex systems that actually do useful stuff.
This kind of algorithm is normally expected to be written, tested, debugged and presented in one hour in programming competitions with fifteen year-old contestants. And it's only the algorithm that Prolog would help you with in this case; it's the whole application on the exterior where all the real polish goes, where the testing is more subtle. Writing the core algorithm of a packing problem, or a routing problem, is completely trivial compared to the work that goes into the interface for entering the data. Programming competitions work with a text input file to get rid of this complexity. I speak as one who has competed in and won such competitions.
And FWIW, I don't think GC is a productivity win because managing dynamic memory is not trivial. Managing dynamic memory is trivial, but it's tedious, and it warps your program design, forcing it to be more imperative, more mutable and less functional. The cost of manual management isn't in managing the memory per se, but in managing the complexity of an application that can't rely on GC to manage the memory.
IMO GC's productivity win comes from the lowered bookkeeping costs of more modular and expressive programming styles - most notably in the ability to return newly allocated structures as return values from functions without having to negotiate away the ambiguity as to who owns them. It lets you built data structures that may share substructure, and write transformations over them which may or may not rewrite parts of the substructure, and the transformation may or may not be memoized etc. Doing this with GC is straight-forward; handling all these options with manual memory management requires ownership handoff protocols, shared ownership hacks (e.g. reference counts), inflexible conventions, a preference to mutate rather than return new, etc., greatly increasing code complexity.
And I speak of GC as someone who these days normally writes in a non-GC language, but have implemented garbage collectors, both on the compiler (metadata) and runtime (the marking and sweeping) sides.
Would you deploy this code in a production application?
"Programming competitions work with a text input file to get rid of this complexity. I speak as one who has competed in and won such competitions."
So are you then saying that these kinds of problems take about an hour to solve, assuming you are someone who competes in and wins timed programming competitions? Also, what will be the maintenance costs of changing requirements going forward, as compared to adding Prolog clauses?
Having said that, most problems we solve here are NP-Complete, most of the time the trivial pruning you are mentioning does not really extend the limits for the computation.
The knapsack problem, as you know, is NP-Complete.
It's definitely not rocket science. 15 year old kids have been doing this for years in IOI etc.
In other words: an ad hoc, informally-specified, bug-ridden, slow implementation of half of Prolog.
I agree that Prolog would probably fare better as an embedded language like Lua, though - it's best suited to things like rules engines and parsers, rather than whole applications.
Most of these kinds of problems are only about 100 lines of code even in fairly verbose languages, depending on how complicated the set you need to permute / select from is, and how complicated your clauses are.
I speak from experience here, solving packing problems in programming competition questions. Pretty much any high school / college programming competition includes one of these kinds of problems, and the time budget is rarely a lot more than an hour, as it's usually one of the simpler questions.
I guess programming an open-ended system would have taken the 15-year-olds an extra 6-7 minutes.
What a lot of this ends up coming down to is the domain expertises of the code author. If you're uncomfortable with recursion, or writing simple interpreters, then Prolog is a much bigger win. Otherwise, it has a higher hurdle to climb.
Interpreters themselves are pretty trivial. Writing a parser and interpreter for a simple expression language (no control flow or anything like that, just a predicate possibly with some arguments) should by itself take no more than an hour. I know from past experience it takes me about 25 minutes, as it's one of the first things I do when I learn a new language.
Shame on me for being snarky.
This is true when the problem is stable and well-specified, but when constraints are being added and removed, when there are "nice-to-have" constraints that save money but may become less tractable as the problem scales, when customers want you to experiment with novel constraints -- you do not want to maintain a homebrew imperative implementation. (I can't say anything about a functional version.) Making your implementation maintainable is tantamount to re-implementing a powerful, general-purpose system such as Prolog.
They could also use it for "debugging" training problems. He had a story about a dolphin who would apparently ignore a specific instruction and just sink down into the tank. They were able to use the simulator to figure out that the problem was not with the dolphin, but with both the instruction given and the surrounding environment at the time they would give the instruction. It turned out the dolphin was actually "following the rules", but the trainers failed to see it.
He also talks about using Prolog to build a scheduling system. Access to trained dolphins is a precious resource and it was important to find the optimal schedule for research. With a handful of facts and rules, Prolog was able to discover it for them. Pretty neat stuff.
I also liked _Clause and Effect_, which is somewhat like a "Little Schemer" for Prolog, with a couple fairly substantial projects at the end. "Learn Prolog Now" (http://www.learnprolognow.org/) is free online, but a bit basic.
CTM has a great chapter on relational programming and Prolog, too - Peter Van Roy worked on Aquarius Prolog (http://www.info.ucl.ac.be/~pvr/Peter.thesis/Peter.thesis.htm...), and he also follows up with constraint programming. I highly recommend using a Prolog with constraint programming libraries, because it will make a big difference when Prolog's default behavior is too naive.
I would recommend learning Prolog, because it's sufficiently different from every other language that it will change the way you think, and even if you never use it in production, it's an excellent prototyping language. As a bonus, learning Prolog will help with Erlang, and vice versa. (Erlang was initially a DSL on SICStus Prolog, and many Prolog idioms came along.)
The (at the time de-facto) standard for Prolog shifted between the two editions, and the latter has several more chapters with larger example projects. Still, the core of the book is about logic programming itself, with Prolog is used an example language.
Turns out it's still available at Amazon.de, just ordered it along with "Clause and Effect".
As far as Erlang I have always been put off by the lack of backtracking. They took the best feature from Prolog and threw it out. Everything else is already strange and quite awkward, and those are the parts they kept but threw away backtracking. (I am looking at Elang as a general purpose language here, I know that there is no need for backtracking in a realtime telephony system).
By the way, if you want to experiment with prolog try SWI prolog. It's open, it has an IDE and a bunch of modules, including support for CHR (constrain handling rules).
Ubuntu has it in its apt repository so you can just install from there.
Keep in mind you will not learn enough about any of these languages that you can run off and build something. Each chapter covers a different language and primarily discusses some of the features of each that you may not see in another. It's kind of like a programming language buffet where you can have a small taste of a bunch of different things.
PL/SQL doesn't give you nice stack traces when you have an error, I just knew the entry point and the place where the error occurred.
Even knowing the data coming in to the entry point, use of the globals meant that you often couldn't know for sure what route the code would take.
I wrote a primitive PL/SQL parser (in Perl) to turn the call tree into Prolog rules, and then used Prolog to give me the possible routes between the entry point and the error location, making debugging much easier.
Basically the perl pulled a list of scoped function names from the DDL, did a text index on the executable code, and searched the index for references to those functions, creating a list of [from.function, to.function] pairs that I fed into prolog.
Next question - Who's going to maintain it?
I mean, props for using Prolog to tackle the complex problem and save gobs of money/time, but doesn't an approach like this seem _really_ risky?
I find its syntax nice and lispish :)
[edit]s/it's/its/