2016-05-20 4 views
0

Я пытаюсь реализовать предикат, который разбивает список целых чисел в двух заданных других предикатах в качестве аргумента. Определение дается следующим образом:Список разбиений Prolog по предикату - как проверить результат предиката?

split(P, L, L1, L2), 

где:

P - predicate to split upon 
L - list to split 
L1 - result list of integers that return true on predicate check 
L2 - result list of integers that return false on predicate check 

Я пытаюсь изменить этот код, который разделяет список с закодированными проверить, является ли целое число в вопросе больше/меньше или равно X (это работает):

split(X, [], [], []). 
split(X, [H|T], [H|L1], L2) :- H=<X, split(X, T, L1, L2). 
split(X, [H|T], L1, [H|L2]) :- H>X, split(X, T, L1, L2). 

для целей тестирования, я скопировал предикат из RosettaCode, чтобы проверить, если число четное следующим образом:

even(N) :- 
(between(0, inf, N); integer(N)), 
0 is N mod 2. 

А вот моя модификация кода выше, но она возвращает «Синтаксическая ошибка: Оператор ожидается» на двух последних строках:

split2(P, [], [], []). 
split2(P, [H|T], [H|L1], L2) :- P(H), split2(P, T, L1, L2). 
split2(P, [H|T], L1, [H|L2]) :- \+ P(H), split2(P, T, L1, L2). 

Я думаю, что моя ошибка в проверке, возвращает ли предикат истинным или false, но не может найти подходящего способа сделать это.

EDIT: Забыл добавить свой вызов для этого:

?- split2(even,[2,7,4,8,-1,5],L1,L2) 

ответ

1

Вы не можете называть предикат, как это, вам нужно использовать call:

?- A = between(0,3,1), A. % OK, because A can be evaluated as it is 
A = between(0, 3, 1). 

?- A = between, A(0,3,1). % won't work 
ERROR: Syntax error: Operator expected 
ERROR: A = between, 
ERROR: ** here ** 
ERROR: A(0,3,1) . 
?- A = between, call(A, 0, 3, 1). % OK, using call 
A = between. 

?- A = between(0, 3), call(A, 1). % Partial application 
A = between(0, 3). 

Имейте в виду, что есть уже предикаты библиотеки, которые выполняют именно то, что вам нужно, см. library(apply), особенно. include/3. Вы также должны посмотреть at the implementation, так как он немного отличается от того, что вы делаете, и не оставляет позади точек выбора.

PS: Перестановка аргументов, чтобы входной список был спереди, является первым шагом на пути к тому, чтобы сделать это детерминированным. Вы также должны избавиться от точки выбора, вызванной двумя статьями, с call(P,H) и с \+ call(P,H). Вы можете сделать это с помощью ->, как в библиотеке SWI-Prolog.

Или, может быть, вас не беспокоят точки выбора или вы хотите сделать более общий предикат. Я уверен, что здесь есть решения в Stackoverflow на теге Prolog.

+0

«Уже есть предикаты библиотеки, которые делают именно то, что вы после». - Я так полагаю, но я хотел бы написать сам, чтобы узнать Prolog. Если бы вы могли подробнее рассказать о своем ответе, я был бы очень благодарен. Как вы можете видеть из моего вопроса, я новичок в Prolog, и я действительно не знаю, как это исправить, любая помощь очень ценится (я пытаюсь это сделать Google, но это сложно, когда вы не знаете, что искать). Требуется ли для исправления моего вопроса много изменений? – Asunez

+0

@Asunez прошу перечитать мой ответ. Я воспроизвожу вашу ошибку с помощью упрощенного примера и покажу вам, как его исправить. –

+0

@Asunez Если вам нужно было нажать на ссылки, которые я предоставил, особенно тот, который показывает реализацию 'include/3', вы увидите пример использования' call' для оценки предиката. Чтение кода других людей является одним из самых фундаментальных способов обучения программированию. –

Смежные вопросы