Это легко достигается с помощью рекурсии в Прологе.Помните, что все в Прологе является либо переменной, либо термином (атомы - это просто 0-арные термины), поэтому термин , подобный следующему:
[a,[[3]],b,4,c(5),4]
... легкодеконструированный (также обратите внимание, что синтаксис списка [..]
является сахаром для двоичного предиката ./2
).Prolog предлагает ряд предикатов для тестирования для определенных типов терминов, таких как числа, строки или составные термины (такие как compound/1
).
Чтобы построить предикат, который вам нужен, я рекомендую написать его, используя несколько предикатов, таких как:
dcountSublists(In, Out) :-
% analyze type of In
% based on type, either:
% 1. split term into subterms for recursive processing
% 2. term cannot be split; either replace it, or pass it through
Вот пример, который поможет вам начать работу, которая решает сложную задачу.Следующее распознает составные термины и разбивает их на части с помощью термина de / constructor =../2
:
dcountSublists(In, Out) :-
% test if In has type compound term
compound(In),
% cut to exclude backtracking to other cases below this predicate
!,
% deconstruct In into functor and an argument list
In =.. [Func|Args],
% apply dcountSublists/2 to every argument, building new args
maplist(dcountSublists, Args, NewArgs),
% re-construct In using the new arguments
Out =.. [Func|NewArgs].
dcountSublists(In, Out) :-
% test if In has type atom
atom(In), !,
% pass it through
Out = In.
Тестирование:
?- dcountSublists([a,[[e]],b,a,c(s),a], L).
L = [a, [[e]], b, a, c(s), a].
Обратите внимание, что это не работает, есливходной термин имеет числа, потому что у него нет предиката для распознавания и обработки с ними.Я оставлю это на ваше усмотрение.
Удачи!