Learn Prolog now
learnprolognow.org
learnprolognow.org
Also, if you learn Prolog, don't forget to learn the constraint programming extensions! SWI and GNU Prolog are free Prologs with constraint programming included. It makes Prolog much more practical.
They added quite a bit of material to the latter chapters, and it updated to the newer, then de-facto standard Prolog (which became an ISO standard in 1995). Useful Prolog implementations usually have non-ISO extensions for module systems, constraint programming, etc.
I have both. I keep the first edition at the office, and it's my lending copy.
Oh, well. Saving $30 on a language I'm not likely to use is probably a Good Thing.
x = 2y + z^2
provide a dataset of x, y, and z tuples with associated error distributions, and ask questions like "what is three-sigma confidence interval for the model given this dataset", and "what would tunable parameters a and b have to be for the most consistent account".
Ideally, it'd be able to take into account convolutions, as well.
* Rather like chapter 4 of SICP, on making metacircular evaluator Prologs.
You should submit this as an HN post too. Thanks!
http://en.wikipedia.org/wiki/Fril
It is a lisp-y prolog that supports fuzzy relations (confidence interval for predicates).
It is not bad if fuzzy logic is your cup of tea.
Here is the reference:
http://www.enm.bris.ac.uk/ai/martin/FrilManual/index.html
Code example (from reference doc of goal set (gs) predicate):
((test a)) : (0.5 0.8)
((test b)) : (0.7 0.9)
qs ((test X) (test Y))
((test a) (test b)) : (0.25 0.64)
((test a) (test b)) : (0.35 0.72)
((test b) (test a)) : (0.35 0.72)
((test b) (test b)) : (0.49 0.81)
no (more) solutions
yes
EDIT: more examples and explanation by its author, Trevor Martin from Bristol Univ.ftp://ftp.cs.cmu.edu/user/ai/areas/fuzzy/com/fril/fril.txt
One formalism for this is Markov Logic.
http://www.cs.washington.edu/homes/pedrod/papers/pilp.pdf
Alchemy is an implementation of Markov Logic.
http://alchemy.cs.washington.edu/
Both of these are from Pedro Domingos, who does a lot of research in this area.
I actually wrote my Masters' project on transistor sizing in Prolog. A fascinating experience, although at the time it was horrible for numeric work. I wound up hacking the interpreter to include a couple of optimizations otherwise I'd probably still be waiting for it to finish :-)
We had to write Pascal interpreter in Prolog - that was an experience. I strongly suggest to everybody to try Prolog - then you will understand why it is good idea to use declarative languages as much as possible when building product (including SQL).
However, the key of learning Prolog to teach you how to expresses the logic of a program/system without describing its control flow. Basically to describe what the program or system should accomplish (which rules govern the program or system) without thinking how these things will be implemented and executed (it will just happen). This kinda of thinking can be very powerful tool when designing complex systems and products.
A look at a simple (although very inefficient) Fibonacci program will illustrate the difference. In Haskell, it'd look something like this: (and work like you might expect)
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
The obvious direct translation to Prolog (I'm using SWI Prolog[0]) is something like this: /* fib(N,X): X is the Nth fibonacci number */
fib(0,0).
fib(1,1).
fib(N,X) :-
N1 is N-1,N2 is N-2,
fib(N1,A),fib(N2,B),
X is A+B.
This, however, is going to cause problems if you actually try to run it, and the reason is that Prolog doesn't just do pattern matching: it attempts to unify the query term (the thing you give it) with the program terms (the things on the left in the program above), and instead of just using the first result that matches, it will (if you ask it to do so) return every possible result by doing a left-to-right depth-first search on the solution tree (using a process called SLD resolution[1]). The expected behavior of the above program is something like this: ?- fib(0,X).
X = 0 ;
false. /* there are no more possible matches */
What's actually going to happen though is this: ?- fib(0,X).
X = 0 ;
/* runs forever */
When you give it the query fib(0,X), it first unifies that with fib(0,0), and the first answer is what you expect: X = 0. The difference occurs when you ask it for another answer (which you do in the interpreter by typing a semicolon). What you want Prolog to say is that there are no other answers, because there's only one 0th Fibonacci number. What Prolog actually does though is it backtracks[1] and goes back up the resolution tree to see if there are any more program terms the query can be unified with. In this case there are: fib(0,X) can unify with fib(N,X) also. Prolog soon gets into negative numbers (and past the base cases), and so ends up running forever.One possible corrected version is below:
fib(0,0).
fib(1,1).
fib(N,X) :-
N > 1,
N1 is N-1,N2 is N-2,
fib(N1,A),fib(N2,B),
X is A+B.
Here, we ensure that we only unify with the third query when N is large enough that we don't match the first two, and so we get the output we'd expect.[0] http://www.swi-prolog.org/ [1] http://en.wikipedia.org/wiki/SLD_resolution [2] http://en.wikipedia.org/wiki/Backtracking
if statements are not horn clauses. if statements are procedural and specify execution order and don't pattern match.
prolog's execution is resolution, done using unification over logic variables.
as a simple example: member/2
member(X,[X|_]). member(X,[_|T]) :- member(X,T).
if I query: member(1,[1,2,3]) this is true
if I query:
member(X,[1,2,3]), this is true, for X=1, X=2 and X=3
similarly you can ask append([1,2,3],[4,5,6],X) to get X=[1,2,3,4,5,6]. and ask append([1,2,3],X,[1,2,3,4]) to get X=4
for example:
to produce all possible combinatons of items from a series of lists:
comb([],[]) comb([H|T],[X|Y]) :- member(X,H), comb(T,Y).
so if I do
comb([[a,b,c],[d,e,f],[g,h,i]],X) I get X = a,d,g or X = a,d,h and so on and so on
as you might see, it is a little bit more obvious that it isn't just a series of 'if statements' but a series of relations between clauses
Unification is far more powerful than pattern matching, which (among other things) supports working with partial information - you can pass around a list of cons cells where the cdr is an unbound variable, and then bind it to another cons cell with an unbound cdr to get O(1) appending, for example. (These are called difference lists.) Same can be done with trees and other, more complex data structures. In effect, rather than fully immutable or fully mutable variables, you get variables that can only be set once, and then semantically "always were" that value. (but possibly undone on backtracking)
Backtracking means that pattern-matching a variable isn't just pass/fail, but potentially a generator (AKA "iterator", etc.) for all matching values. Sometimes (ok, often) the ensuing combinatorial explosion keeps it from scaling efficiently to real problems, but constraint programming compensates, pruning off a LOT of the space of potential solutions before searching. And, saying, "here's my problem, throw everything at it and figure it out" in very few lines of code is still great for prototyping.
Comparing Prolog to Erlang makes the difference clearest, to me. Erlang doesn't do backtracking (because it throws soft-real-time guarantees out the window!) or full unification (because passing around and subsequently binding unbound variables would be a form of non-local state). Erlang is still a great language IMHO, but it's a very different kind of language, because those two features are what make Prolog Prolog.
I can't help but notice that the webpage looks like one of the awful default Beamer presentation styles.