4

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

Jacek
  • 1,048
  • 15
  • 21

4 Answers4

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.

mat
  • 40,498
  • 3
  • 51
  • 78
  • 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).` – Jacek Apr 03 '17 at 12:30
  • Ah yes, `library(lambda)` is included in YAP, but SWI requires this small extra step. – mat Apr 03 '17 at 12:39
5

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://stackoverflow.com/a/34917391/2471388.

Jakub Mendyk
  • 428
  • 2
  • 6
  • 14
4

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.
CapelliC
  • 59,646
  • 5
  • 47
  • 90
  • Good to know, thanks! Pity, I can only suggest one answer as this is probably the "right" way for swi-prolog. – Jacek Apr 04 '17 at 11:19
  • 1
    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... – CapelliC Apr 04 '17 at 11:23
  • 1
    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. – false Apr 04 '17 at 14:35
  • @false: given how many extensions SWI-Prolog has to offer, this isn't a surprise. – CapelliC Apr 04 '17 at 15:32
  • 1
    You say that *because* there are many extensions, the basis should be changed too? – false Apr 04 '17 at 15:42
  • 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. – CapelliC Apr 04 '17 at 15:50
  • 1
    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. – false Apr 04 '17 at 16:12
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.

Community
  • 1
  • 1
s0nata
  • 194
  • 1
  • 7
  • 1
    Thanks, I didn't realise this. Unfortunately, in the SWI-prolog CLI the _C variable is dully output. – Jacek Apr 06 '17 at 14:03