grandparent(G,G1) :- parent(X, _), parent(G, X).
grandmother(G,G1) :- grandparent(G,G1), female(G).
grandfather(G,G1) :- grandparent(G,G1), male(G).
but the last 2 predicates bother me because they are the same save for
the gender of the grandparent.
I'm wondering if there are advanced Prolog features which allow for
generating the grandmother/2 and grandfather/2 predicates from a
common template.
E.g. Here is a Perl progam that does what I want:
sub make_grandparent {
my ($grandparent_type)=@_;
my %map = (
grandmother => 'female',
grandfather => 'male'
);
my $predicate = $map{$grandparent_type};
sprintf 'grandparent(G,G1) :- grandparent(G,G1), %s(G).',
$predicate;
}
for my $grandparent qw(grandmother grandfather) {
print make_grandparent($grandparent) . "\n" ;
}
/* Transcript */
[tbrannon@Ghostdc7600] [~/prg/prolog] perl mkgp.pl
grandparent(G,G1) :- grandparent(G,G1), female(G).
grandparent(G,G1) :- grandparent(G,G1), male(G).
> I'm working through the Amzi prolog tutorial and wrote a couple of
> predicates which describe what a grandmother and grandfather are:
>
> grandparent(G,G1) :- parent(X, _), parent(G, X).
> grandmother(G,G1) :- grandparent(G,G1), female(G).
> grandfather(G,G1) :- grandparent(G,G1), male(G).
>
> but the last 2 predicates bother me because they are the same save for
> the gender of the grandparent.
In addition, consider using predicate names that make clear which
argument is what, like grandparent_of/2, grandmother_of/2 etc. Also, G1
occurs only once in the first clause.
> I'm wondering if there are advanced Prolog features which allow for
> generating the grandmother/2 and grandfather/2 predicates from a
> common template.
Consider for example:
?- member(Functor-Constraint, [grandmother_of-female, grandfather_of-male]),
Head =.. [Functor,X,Y],
Goal =.. [Constraint,X],
portray_clause((Head :- grandparent_of(X, Y), Goal)),
false.
yielding:
grandmother_of(A, B) :-
grandparent_of(A, B),
female(A).
grandfather_of(A, B) :-
grandparent_of(A, B),
male(A).
> E.g. Here is a Perl progam that does what I want:
>
> [tbrannon@Ghostdc7600] [~/prg/prolog] perl mkgp.pl
> grandparent(G,G1) :- grandparent(G,G1), female(G).
> grandparent(G,G1) :- grandparent(G,G1), male(G).
This only creates additional clauses for grandparent/2, and none for
grandmother_of/2 and grandfather_of/2.
--
comp.lang.prolog FAQ: http://www.logic.at/prolog/faq/
?- member(F-C, [grandmother_of-female, grandfather_of-male]),
format("~w(X, Y) :- grandparent(X, Y), ~w(X).\n", [F,C]),
false.
it yields:
grandmother_of(X, Y) :- grandparent(X, Y), female(X).
grandfather_of(X, Y) :- grandparent(X, Y), male(X).
> In addition, consider using predicate names that make clear which
> argument is what, like grandparent_of/2, grandmother_of/2 etc. Also, G1
> occurs only once in the first clause.
I see. I suppose as long as you enforce the convention that
predicate(A,B) is interpreted as
A 'is' predicate 'of' B
then you can get rid of the extra _of.
>
> > I'm wondering if there are advanced Prolog features which allow for
> > generating the grandmother/2 and grandfather/2 predicates from a
> > common template.
>
> Consider for example:
>
> ?- member(Functor-Constraint, [grandmother_of-female, grandfather_of-male]),
> Head =.. [Functor,X,Y],
> Goal =.. [Constraint,X],
> portray_clause((Head :- grandparent_of(X, Y), Goal)),
> false.
It seems there are 3 things here that I dont understand. Where can I
read on:
1 - What function is the dash serving in member(Functor-Constraint,
[grandmother_of-female, grandfather_of-male])?
2 - the "=.." syntax?
3 - portray_clause/2. I'm using SWI Prolog and dont know if that is
built in.
>
> yielding:
very nice.
>
> This only creates additional clauses for grandparent/2, and none for
> grandmother_of/2 and grandfather_of/2.
OK, fixed:
/* PROGRAM */
sub make_grandparent {
my ($grandparent_type)=@_;
my %map = (
grandmother => 'female',
grandfather => 'male'
);
my $predicate = $map{$grandparent_type};
sprintf '%s(G,G1) :- grandparent(G,G1), %s(G).',
$grandparent_type,
$predicate;
}
for my $grandparent qw(grandmother grandfather) {
print make_grandparent($grandparent) . "\n" ;
}
/* TRANSCRIPT */
[tbrannon@Ghostdc7600] [~/prg/prolog] perl mkgp.pl
grandmother(G,G1) :- grandparent(G,G1), female(G).
grandfather(G,G1) :- grandparent(G,G1), male(G).
[tbrannon@Ghostdc7600] [~/prg/prolog]
> 1 - What function is the dash serving in member(Functor-Constraint,
It seems to be doing something like 'unzip' would do in a functional
programming language.
> I see. I suppose as long as you enforce the convention that
> predicate(A,B) is interpreted as
>
> A 'is' predicate 'of' B
>
> then you can get rid of the extra _of.
Consider using a more descriptive name, like parent_child/2.
> 1 - What function is the dash serving in member(Functor-Constraint,
Any functor will do; it is customary to use -/2 for pairs.
> 2 - the "=.." syntax?
http://www.swi-prolog.org/pldoc/doc_for?object=%28%3d..%29%2f2
> 3 - portray_clause/2.
I used portray_clause/1, not .../2, see:
http://www.swi-prolog.org/pldoc/doc_for?object=portray_clause%2f1
>
> > 1 - What function is the dash serving in member(Functor-Constraint,
>
> Any functor will do; it is customary to use -/2 for pairs.
>
I do not see -/2 listed in the predicate reference:
http://www.swi-prolog.org/pldoc/doc_for?object=section%282%2c%20%27F.1%27%2c%20swi%28%27%2fdoc%2fManual%2fpredsummary.html%27%29%29
Also I do not see a member/2 listed there either.
I'm sorry if I'm asking too many questions, but I almost have this
figured out.