user1204349
user1204349

Reputation: 167

prolog facts and variables

I was just wondering how I would make a fact such as

family(original, [dad/1, mom/2, child/5, granny/10]).

where original would be the name of the family, and the list is composed of titles and speeds.

how do I separate the number from the title (eg. dad/1), so I can do something like this:

time_needed(dad,1).
time_needed(mom,2).
time_needed(child,5).
time_needed(granny,10).

Upvotes: 1

Views: 291

Answers (2)

m09
m09

Reputation: 7493

What you wrote in your example is fine. You can make pairs with any delimiter that is declared as infix binary operator. That includes /, +, ,, - etc... You can then pattern match pairs this way thanks to unification:

test :-
    family(X, [Title/Speed|_]),
    time_needed(Title, Speed).

Here I only pattern matched the first element but you can see the idea.

Though, note that usually - is used instead of / to delimit pairs. In particular, if you use SWI, the pairs library uses a Key-Value syntax.

Upvotes: 2

CapelliC
CapelliC

Reputation: 60014

You need to assert elements of the list. Note that this way you lose the original key.

:- dynamic time_needed/2.
assert_family(Key) :-
  family(Key, List),
  assert_list(List).

assert_list([]).
assert_list([N/V|Es]) :-
  assertz(time_needed(N, V)),
  assert_list(Es).

and you call assert_family(original).

If your Prolog has forall/2 (or maplist/2 + library(lambda)) the code could be more compact:

:- dynamic time_needed/2.
assert_family(Key) :-
  family(Key, List),
  forall(member(N/V, List),
         assertz(time_needed(N, V))).

i.e. the recursive loop now it's 'inlined' in forall/2. But that library predicate hides behind syntactic simplicity some weird behaviour... Go with the simpler recursive loop.

Upvotes: 1

Related Questions