Prolog: ignore unwanted variables in the output
Asked Answered
F

4

5

Is there a way to force the prolog CLI to return query results with only the variables I'm interested in? A simple example would be:

?- mother(M, C1), father(F, C1).

which returns bindings for all M, F and C1. But I'm interested only in M and F, while C1 is just clutter. In this simple example it's not bad but for longer queries with many helper variables it's much more vexing.

Is there a simple way to express that via the query; I mean without defining a separate rule?

Cheers, Jacek

Floatable answered 3/4, 2017 at 11:50 Comment(0)
P
6

A very straight-forward way to do this is to use library(lambda) by Ulrich Neumerkel.

For example, in your case, given the sample facts:

mother_child(m, c).
father_child(f, c).

We get for your query:

?- mother_child(M, C),
   father_child(F, C).
M = m,
C = c,
F = f.

We would like to project away the variable C.

So we wrap the whole query inside a lambda expression such that only M and F have global scope and hence are reported by the toplevel:

?- M^F+\(mother_child(M, C),
         father_child(F, C)).
M = m,
F = f.

This obviously becomes all the more useful the more variables you want to project away. You only need to specify the variables you want the toplevel to report.

Pantia answered 3/4, 2017 at 12:4 Comment(2)
Exactly what I needed. Many thanks! Just to mention in swi-prolog lambda is an extra package that needs to be added using pack_install(lambda).Floatable
Ah yes, library(lambda) is included in YAP, but SWI requires this small extra step.Pantia
L
6

In the case of SWI-Prolog, it offers a flag to hide variables that start with an underscore. To change the settings execute goal

set_prolog_flag(toplevel_print_anon, false).

in SWI-Prolog session. Alternatively, you can add it to your .swiplrc.

More detailed answer with examples is provided at https://mcmap.net/q/1899516/-prolog-in-a-query-how-to-put-a-condition-on-a-variable-that-i-do-not-want-in-the-results.

Likable answered 1/5, 2019 at 17:46 Comment(0)
A
5

In SWI-Prolog, library(yall) offers the functionality you're after, and more.

?- {M,F}/(mother_child(M, C),father_child(F, C)).
M = m,
F = f.
Arlberg answered 3/4, 2017 at 17:25 Comment(7)
Good to know, thanks! Pity, I can only suggest one answer as this is probably the "right" way for swi-prolog.Floatable
Yes, I avoided to comment about the performance of the libraries, but you can compare them easily, and draw your conclusions. library(yall) has been engineered by great Prolog developers, to overcome the relative inefficiency of the highly required lambda functionality. OTOH, it's a SWI-Prolog only feature...Arlberg
For completeness, also note that this library relies on a SWI-specific module extension. Further it would require a SWI-specific type checker that does not fit into the common scheme of polymorphic type checking.Unexpressed
@false: given how many extensions SWI-Prolog has to offer, this isn't a surprise.Arlberg
You say that because there are many extensions, the basis should be changed too?Unexpressed
I don't follow... sorry. I'm unaware of the specific extension you're referring, my comment was just 'pour parler'. I don't ever know how SWI-prolog modules relate to ISO modules.Arlberg
Simply look at the meta_predicate declarations in the yall module: they use : instead of a precise number. That is, the interface alone cannot maintain consistency - there is some extra mechanism for that.Unexpressed
I
0

Maybe it would suffice to use an "auxiliary variable syntax" with _ for those helper variables of yours?

Notice the difference between the uses of C and _C in the queries: SWHISH interface

See also this answer about the (anonymous) variables in Prolog.

Incombustible answered 5/4, 2017 at 16:30 Comment(1)
Thanks, I didn't realise this. Unfortunately, in the SWI-prolog CLI the _C variable is dully output.Floatable

© 2022 - 2024 — McMap. All rights reserved.