2
votes

In Erlang and Haskell there is way to capture the whole pattern match. For example, in Erlang:

% We can capture the whole match of list, and not only inner part of structure
% like head and tail.
match_list([H|T]=F) -> hd(F).

I wonder how this can be done in Prolog. How to get the whole term without reconstructing it by hand:

match_list([H|T]) :-
    % quite awkward, how to back-reference to it automatically?
    F = [H|T], ...

I've tried to solve next task. There are a lot of family-relations specified as a set of facts(resembles part of chapter4 Bratko book). I want to create predicate which returns specific family from this set of families. Currently solution looks like this:

family(
  person(tom, fox, date(7,may,1950), works(bbc,15200)),
  person(ann, fox, date(9,may,1951), unemployed),
  [
    person(pat, fox, date(5,may,1973), unemployed),
    person(doris, fox, date(8,may,1973), unemployed),
    person(kate, fox, date(5,may,1973), unemployed),
    person(jim, fox, date(6,may,1973), unemployed)]).
% ... here goes another family

foxs(F) :-
  family(person(_, fox, _, _), W, CL),
  family(H, W, CL),
  F = family(H, W, CL).

As you can see, at first foxs-goal looks-up into family database and capture wife(W) and children(CL). In second clause it captures husband(H). In third it reconstructs family. And I don't like this stuff. In Erlang or Haskell I can match family and capture it, so there is no need for second and third part.

I googled and stackoverflowed, but without a luck. Maybe somebody can point me in a right direction?

PS: I use SWI-Prolog.

2

2 Answers

1
votes

Use Prolog's built-in unification, which is a generalization of pattern matching. For example, what about:

match_list(List) :- List = [L|Ls], ... .

In your foxs/1 example, since F is only used in the head, you can pull the explicit unification ((=)/2) into the head:

foxs(family(H, W, Cs)) :-
    family(person(_, fox, _, _), W, Cs),
    family(H, W, Cs).

However, you probably rather need instead:

foxs(family(H, W, Cs)) :-
    H = person(_, fox, _, _),
    family(H, W, Cs).
1
votes

a shorter pattern could be

foxs(F) :-
  F = family(person(_, fox, _, _), person(_, fox, _, _), _),
  call(F).  % was F.