#prolog
#prolog
Вопрос:
Я работаю над предикатом only_atoms /2 (список , результат-), который я хотел бы фильтровать неатомами.
Например :
only_atoms([1, 2, X, h(Y), 'aba'], Result).
должен возвращать
Result = [1, 2, 'aba'].
Меня не волнует порядок.
Вот фрагмент кода, который я придумал :
only_atoms([], []) :- !.
only_atoms([Head | Tail], [Head | Result]) :-
atom(Head),
!,
only_atoms(Tail, Result).
only_atoms([_ | Tail], Result) :-
only_atoms(Tail, Result).
Я думал, что это правильное рассуждение для решения такой проблемы, но, похоже, оно неверно, поскольку оно дает мне [] (редактировать : на самом деле это дает [aba], см. Уточнения ниже, мой плохой !) несмотря ни на что. Я был бы признателен за помощь!
Ответ №1:
Первая подсказка: для 1
и 2
, atom
возвращает false
.
Кстати, я искал предикат filter, в стандартной библиотеке он вызывается include
, обычно лучше, если вы используете то, что уже предоставляет язык 😉
?- include(atom, [1, 2, X, h(Y), 'aba'], Result).
Result = [aba].
или, если вы хотели просто отфильтровать переменные:
?- exclude(var, [1, 2, X, h(Y), 'aba'], Result).
Result = [1, 2, h(Y), aba].
Еще, кстати, одно любопытное различие между вашим only_atoms
и использованием include(atom, ...)
заключается в том, что ваш будет объединять переменные в первом списке с атомами во втором списке, тогда как include
не будет.
?- only_atoms([1, x, 2, Y], [x, y]).
Y = y.
?- include(atom, [1, x, 2, Y], [x, y]).
false.
Эти тонкости пролога всегда меня удивляют (наверное, это потому, что я не уделял достаточно внимания в университете xD).
Комментарии:
1. Хм, я смущен, я был уверен, что проверил atom на наличие констант и переменных. Затем я снова проверил типы данных в prolog и обнаружил, что числа и строки не были одинаковыми константами ~~ Спасибо, я просто добавил ;number (Head) после atom (Head), и это работает нормально. Еще раз извините за неудачные предположения; (
2. Я думал, что это было известно, и цель была
['aba']
единственной.3. @Orbling — OP сообщал, что результатом был пустой список. Я не понимаю, как это решает эту конкретную проблему, но OP говорит, что это так, так что все хорошо, что хорошо заканчивается.
4. да, я действительно думал, что числа, атомы и так Далее Были константами и обрабатывались одинаково, поэтому мой пример кода был только числовым, а в этом, как оказалось, были атомы, это моя ошибка.
Ответ №2:
Вероятно, вам нужно заставить Head
не быть атомом в предложении alternate, в противном случае это вариант и для атомов.
Это возвращает Result = ['aba']
для меня.
only_atoms([], []).
only_atoms([Head | Tail], [Head | Result]) :- atom(Head), !, only_atoms(Tail, Result).
only_atoms([Head | Tail], Result) :- atom(Head), !, only_atoms(Tail, Result).
В качестве альтернативы вы могли бы попробовать использовать findall/3
.
atoms_list(List, Result) :- findall(Item, (member(Item, List), atom(Item)), Result).
Комментарии:
1. Второе предложение имеет сокращение после
atom(Head)
. Разве это не помешало бы ему выполнить резервное копирование до третьего пункта, когдаHead
это атом?2. да, обычно откат прерывается во втором предложении
3. @Тед Хопп: Я бы не хотел, чтобы он создавал резервную копию, если
Head
это атом. Если я удалю разрез, то выполнение будет ждать, чтобы проверить наличие альтернатив. С сокращением он мгновенно возвращается с определенным ответом.4. Я не предлагал удалять разрез. Я задавался вопросом о необходимости принудительно
Head
не быть атомом в предложении alternate; он не может попасть туда, еслиHead
не является атомом.