Может кто-нибудь сказать мне, что не так с моей идеей?
То, что вы делаете, слишком сложно, вот что не так.Если в качестве входных данных у вас действительно есть действительный составной термин, и вам нужно получить из него список атомарных подтерминов, то вот что вы можете попробовать:
expression_atoms(E) -->
{ compound(E),
E =.. [_Name|Args]
},
!,
expression_list_atoms(Args).
expression_atoms(E) -->
{ atomic(E)
},
!,
[E].
expression_list_atoms([E|Es]) -->
expression_atoms(E),
expression_list_atoms(Es).
expression_list_atoms([]) --> [].
(Редактирование ниндзя: см. Решение Пауло Моуры для более четкой реализации той же идеи.)
Единственная причина, почему это DCG, а не обычный предикат, заключается в том, что я слишкомлень выяснить, как правильно выполнить сложение.
Вот небольшой тест:
?- X = x + y * (-z).
X = x+y* -z.
?- X = x + y * (-z), write_canonical(X).
+(x,*(y,-(z)))
X = x+y* -z.
?- X = x + y * (-z), write_canonical(X), phrase(expression_atoms(X), Atoms).
+(x,*(y,-(z)))
X = x+y* -z,
Atoms = [x, y, z].
В последнем запросе вы можете увидеть атомы, извлеченные из выражения.
Как видите, это решение не заботится об именах составных терминов.Это происходит в строке 3 списка:
E =.. [_Name|Args]
Таким образом, вы можете бросить в него что угодно, и оно все равно будет «работать»:
?- phrase(expression_atoms(
the(naked, truth(about(our(waitresses))), is(that(they(only(flirt, with, you))), to(get(a(better(tip('!')))))))),
Atoms).
Atoms = [naked, waitresses, flirt, with, you, !].
Если вы хотите, чтобы это ни к чему не привелоиначе, кроме предопределенного списка операторов с заданной арностью, вам придется добавить туда немного больше кода.