I done a macroes! It took hours to get right (mainly because of the hideous un-lisp-like blob that I was trying to parse) but I learned a lot about list trees and the way that macros do things.
Anyway, the real reason for this post is that I've just grokked
(amb) and it's a belter.
Fixnum describes it in a very boring, difficult way and then obscures it away behind other macros. It seems to me that (amb) is a tool that's so powerful that it's really worth knowing. So I managed to find
this (explanation in Ruby) and
A/
B (explanations in C). These were also pretty complex, but the content of the four pages interfered constructively. Bear in mind that I've never done any Prolog before, so this might be old news.
In essence, there are two rules:
1. (amb) = FAIL! - calling amb with no parameters is considered a fail
2. (amb 'a 'b 'c) - amb takes a list of parameters and will return one of them. The one that it returns is the first one that doesn't FAIL.
So what you do is you assign values to your vars and then run them through a simple program to see if they meet all the conditions. Hey presto - the results just fall out automatically!
A simple example - you have three vars a,b,c which can each equal the values 1-5. Find a combination where a*b*c=12.
Code: Select all
> (let ((a (amb 1 2 3 4 5))
(b (amb 1 2 3 4 5))
(c (amb 1 2 3 4 5)))
(if
(not (= (* a b c) 12))
(amb))
(display (list a b c)))
-
(1 3 4)
Another example is the map colours one in
fixnum where the actual algorithm boils down to:
Code: Select all
;the color of a country
;should not be the color of
;any of its neighbors
(for-each
(lambda (c)
(assert
(not (memq (cadr c)
(caddr c)))))
countries)
(assert returns (amb) if false).