Brian Rosamilia
Brian Rosamilia

Reputation: 1486

Prolog dict predicate matching

Given this program, why am I forced to define every atom in the predicate, even if they're anonymous. Why is it that undefined variables in a dict predicate aren't thought of as anonymous?

funt2(X) :-
    X = point{x:5, y:6}.

evalfunt(point{x:5, y : 6}) :-
    write('hello world!').

evalfunt(point{x:_, y : _} ) :-
    write('GoodBye world!').

Why can't I just say

evalfunt(point{x:5}) :-
        write('GoodBye world!').

^that won't match, by the way.

I may as well just use a structure if I have to define every possible value in the dict to use dicts.

What's the motivation here? Can I do something to make my predicate terse? I'm trying to define a dict with 30 variables and this is a huge roadblock. It's going to increase my program size by a magnitude if I'm forced to define each variables (anonymous or not).

Upvotes: 1

Views: 1060

Answers (2)

Brian Rosamilia
Brian Rosamilia

Reputation: 1486

I was able to accomplish what I needed by doing the following

checkiffive(Y) :- 
        get_dict(x, Y, V), V=5.

You need to use the built in methods for unifying values from a dict.

Described in chapter 5.4 of the SWI prolog reference

http://www.swi-prolog.org/download/devel/doc/SWI-Prolog-7.1.16.pdf

Upvotes: 1

Eugene Sh.
Eugene Sh.

Reputation: 18331

Dict is just a complex data type, like tuple, which has data AND structure. If you have, for example two facts:

fact(point{x:5, y:6}).
fact(point{x:5}).

Then the query

fact(point{x:_}).

will match the second one, but not the first one. And the query

fact(point{x:_, y:_}).

Will match the first one, but not the second.

Now, if you want to match facts of the form fact(point{x:_, y:_, z:_}) only by one specific field, you can always write a helper rule:

matchByX(X, P) :- fact(P), P=point{x:X, y:_, z:_}. 

So having facts:

fact(point{x:5, y:6, z:1}).
fact(point{x:1, y:2, z:3}).
fact(point{x:2, y:65, z:4}).

and quering

matchByX(1, P).

will return:

P = point{x:1, y:2, z:3}


UPDATE:
Moreover, in SWI-Prolog 7 version the field names can be matched as well, so it can be written in much more generic way, even for facts with different structures:

fact(point{x:5, y:6, z:1}).
fact(point{x:1, y:2}).
fact(point{x:2}).
fact(point{x:2, y:2}).

matchByField(F, X, P) :- fact(P), P.F = X.

So query:

?- matchByField(x, 2, P).
P = point{x:2} ;
P = point{x:2, y:2}.

Upvotes: 4

Related Questions