Search code examples
prologdcg

Using list in Prolog DCG


I am trying to convert a Prolog predicate into DCG code. Even if I am familiar with grammar langage I have some troubles to understand how DCG works with lists and how I am supposed to use it.

Actually, this is my predicate :

cleanList([], []).
cleanList([H|L], [H|LL]) :-
    number(H),
    cleanList(L, LL),
    !.
cleanList([_|L], LL) :-
    cleanList(L, LL).

It is a simple predicate which removes non-numeric elements. I would like to have the same behaviour writes in DCG.

I tried something like that (which does not work obviously) :

cleanList([]) --> [].
cleanList([H]) --> {number(H)}.
cleanList([H|T]) --> [H|T], {number(H)}, cleanList(T).

Is it possible to explain me what is wrong or what is missing ?

Thank you !


Solution

  • The purpose of DCG notation is exactly to hide, or better, make implicit, the tokens list. So, your code should look like

    cleanList([]) --> [].
    cleanList([H|T]) --> [H], {number(H)}, cleanList(T).
    cleanList(L) --> [H], {\+number(H)}, cleanList(L).
    

    that can be made more efficient:

    cleanList([]) --> [].
    cleanList([H|T]) --> [H], {number(H)}, !, cleanList(T).
    cleanList(L) --> [_], cleanList(L).
    

    A style note: Prologgers do prefers to avoid camels :)

    clean_list([]) --> [].
    etc...
    

    Also, I would prefer more compact code:

    clean_list([]) --> [].
    clean_list(R) --> [H], {number(H) -> R = [H|T] ; R = T}, clean_list(T).