Doug Smith
Doug Smith

Reputation: 29314

How do I stop an empty list from appending to a complete list in Prolog?

I have this issue in Prolog where I'm creating a list, and sometimes predicates that contribute to this list creation return an empty list, []. In the end I end up with a list that looks like [[1, 2, 3], []] for example, when I'd rather it be [[1, 2, 3]].

How do I stop that empty list when I return it from being put with the rest of the list? My logic programming isn't terrible strong, but in other languages I'd simply say, if not empty: append, otherwise don't do anything.

Is this possible in Prolog?

EDIT: To put it in an example, say I have the following predicate:

put_together(Value1, Value2, Result) :-
    Result = [Value1, Value2].

I call put_together(1, 2, Result). and get Result = [1, 2] as expected. But if I call, put_together(1, [], Result). I get Result = [1, []] which I don't want, I'd rather have the final empty list gone, which would be simply [1].

Upvotes: 4

Views: 723

Answers (2)

coredump
coredump

Reputation: 38809

If possible, I'd recommend changing your predicates so that you always return lists of lists, and always compose them with append/3. That way, you can absorb empty lists as-if they were zeros in a sum and stop worrying about empty lists being corner cases.

DCG's, as mention in mat's answer, are a possible way to consistently use lists.

Upvotes: 0

mat
mat

Reputation: 40768

DCGs are often a good way to describe lists in Prolog. This makes reasoning about lists a lot easier. You should try it in your use case.

For example, to "put together" (see below for why this is not a good view of the matter) two lists, as you say it, you can use:

lists_together(Ls1, Ls2) -->
        list(Ls1),
        list(Ls2).

list([])     --> [].
list([L|Ls]) --> [L], list(Ls).

Sample cases:

?- phrase(lists_together([a,b,c], [d,e]), Ts).
Ts = [a, b, c, d, e].

?- phrase(lists_together([a,b,c], []), Ts).
Ts = [a, b, c].

This is completely general and works in all directions. Try for example the most general query, or iterative deepening etc. I therefore avoid an imperative name like put_..., which would indicate that it works only in one direction. Instead, I use a more declarative name that does justice to the multiple directions in which this relation holds.

However, in your case, it seems that you are somehow, and involuntarily, mixing terms of different kinds. To denote pairs, do not use [A,B] (which is .(A, .(B, []))), but rather use terms like A-B.

So, to relate such pairs to their components, use for example:

key_value_pair(Key, Value, Key-Value).

Upvotes: 4

Related Questions