3

is it possible to get all elements from list of lists in Prolog?

Something like: We have getElements([[[a,b,[c]],d,e],f,g,[h,[i,j]]],S) and the result is: S = [a,b,c,d,e,f,g,h,i,j] ...

Thanks for help.

false
  • 10,264
  • 13
  • 101
  • 209
kolage
  • 577
  • 9
  • 15

2 Answers2

5

You asked for all elements of a list of lists. That is, for [[1,2,3],[4]] this would be the list [1,2,3,4]. However, for [[[1],[3]]] this would be the list [[1],[3]] since [1] and [3] are elements. For this reason, flatten/2 is incorrect it gives you [1,3] as an answer. Also, for 1 it gives [1]...

Here is a solution using :

seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).

seqq([]) --> [].
seqq([Es|Ess]) --> seq(Es), seqq(Ess).

?- phrase(seqq([[[1],[3]]]), Xs).
   Xs = [[1],[3]].
?- phrase(seqq(1), Xs).
   false.

This solution now works also for cases like the following:

?- phrase(seqq([S1,S2]), [1,2]).
   S1 = [], S2 = [1,2]
;  S1 = [1], S2 = [2]
;  S1 = [1,2], S2 = []
;  false.

Whereas flatten/2 is completely wrong:

?- flatten([S1,S2],[1,2]).
   S1 = 1, S2 = 2.
false
  • 10,264
  • 13
  • 101
  • 209
3

In SWI-Prolog (and maybe others), you can use flatten/2:

?- flatten([[[a,b,[c]],d,e],f,g,[h,[i,j]]], S).
S = [a, b, c, d, e, f, g, h, i|...].

Note that the SWI-Prolog manual page for flatten/2 includes the following statement:

Ending up needing flatten/3 often indicates, like append/3 for appending two lists, a bad design.

However, the page doesn't say whether there is another native predicate to replace it.

I'm sure a better answer will be supplied.

repeat
  • 18,496
  • 4
  • 54
  • 166
magus
  • 1,347
  • 7
  • 13
  • ok thanks :) didnt know it... although I hoped little bit that I'll find out the trick - some algorithm... but thanks ;) (and sorry for my english O:-)) – kolage Mar 19 '12 at 20:29
  • 1
    You can see the source/how it is implemented here.. http://www.swi-prolog.org/pldoc/doc/swi/library/lists.pl?show=src – magus Mar 19 '12 at 22:18
  • 3
    @magus: This predicate is deprecated. Please read it justification in the source you mention: Ending up needing flatten/3 often indicates, like append/3 for appending two lists, a bad design. Efficient code that generates lists from generated small lists must use difference lists, often possible through grammar rules for optimal readability. – false Mar 20 '12 at 10:00