prologclpfdprolog-defaulty

Constrain integer to be in set


I'm using the in/1 predicate to try and constrain an integer to take values from a certain set:

?- use_module(library(clpfd)).

gen_in_set(X) :-
    X in [0, 1, 3, 5, 7].

I didn't expect this to work, since [...] is list notation. I could of course use:

    X #= 0 #\/ X #= 1 #\/ X #= 3 #\/ X #= 5 #\/ X #= 7.

but this is very verbose. The following also works:

    X in 0 \/ 1 \/ 3 \/ 5 \/ 7.

and is a bit shorter, but still quite ugly.

The documentation states:

Var is an element of Domain. Domain is one of:

Integer Singleton set consisting only of Integer.

I've tried searching for what a singleton set is (Prolog newbie here), but I couldn't find anything online. Is there a cleaner way of expressing my constraint?


Solution

  • You can use the (undocumented) {}/1 syntax to explicitly enumerate a set, which is also available in SICStus Prolog:

    ?- X in {0,1,3,5,7}.
    X in 0..1\/3\/5\/7.
    

    Personally, I do not want to encourage a flurry of superfluous notations, in particular if they are (like this variant) defaulty: You cannot distinguish by pattern matching alone if an element is an integer or another disjunction of such domain expressions:

    ?- write_canonical({0,1,3,5,7}).
    {','(0,','(1,','(3,','(5,7))))}
    

    At every place an integer occurs in this representation, a domain expression could also be substituted, making this representation very ambiguous. But in case you need it, it is there.

    In the interest of purity, it would be more appropriate to support a syntax like X in [0,1,3,5,7], because here it is clear what each term means.