LINUX.ORG.RU

[prolog] Простейший вопрос.

 


0

1

Вопрос для понимающего человека скорее всего не сложный. Я просто немного не понимаю способ работы рантайма Пролога.

Есть правило

test(K,N):-K>0,K=<N.

Ничего нет проще. Пишем потом

?- test(1,5).
true.

?- test(7,5).
false.

?- test(X,5).
ERROR: =</2: Arguments are not sufficiently instantiated

Логично, требовать всемогущей магии от интерпретатора нельзя. Даже понятно что значит ошибка. Не понятно как от нее избавиться, что дописать еще. Хотелось бы получить по очереди значения от 1 до 5. Не список, а именно чтобы оно последовательно выводило и ожидало нажатия ";", как если бы правило было

test(1,5).

test(2,5).

test(3,5).

test(4,5).

test(5,5).

Тогда

?- test2(X,5).
X = 1 ;
X = 2 ;
X = 3 ;
X = 4 ;
X = 5.

Вроде бы вопрос пустяковый, но ничего конкретного нигде нет. Я даже вопрос кратко сформулировать не могу.

★★★★★

Последнее исправление: vertexua (всего исправлений: 2)

Нашел это

between(I,J,J):-J>=I.
between(I,J,K):-J>I, J1 is J - 1, between(I,J1,K).

Почему такой костыльный метод!?! Я в шоке.

vertexua ★★★★★
() автор топика
Ответ на: комментарий от vertexua

Почему же костыльный? Чуть изменить порядок следования во втором правиле - вылетит с бесконечной рекурсией.

mclaudt
()

> Логично, требовать всемогущей магии от интерпретатора нельзя

Совершенно верно. Но если магия нужна, почитай про CLP (Constraint Logic Programming) у Братко.

Я даже вопрос кратко сформулировать не могу.

Не беда, мы и так поняли.

runtime ★★★★
()
Ответ на: комментарий от vertexua

> Почему такой костыльный метод!?!

Для работы с числами в Prolog это нормально.

runtime ★★★★
()
Ответ на: комментарий от vertexua

Если вдруг не знал, то обычно исходники можно посмотреть с помощью предиката listing. Но конкретно этот в swi написан на си, так что облом.

dmsh
()
Ответ на: комментарий от vertexua

Он мало того, что слегка костыльный, так он еще и работает не так как стандартный between. Кстати, это довольно кучерявый предикат если аккуратно рассматривать все крайние случаи, не оставлять лишник точек возврата и избегать ненужных вычислений. У меня получилось как-то так:

my_between(From, To, X) :- integer(X), From =< X, X =< To, !.
my_between(From, To, X) :- my_between(From,To,X,From).

my_between(_, inf, X, X).
my_between(From, inf, X, Cur) :- next(From,inf,X,Cur).

my_between(_, X, X, X) :- !.
my_between(From, To, X, Cur) :- Cur < To, ( Cur = X ; next(From,To,X,Cur) ).

next(From, To, X, Cur) :- Cur1 is Cur + 1, my_between(From,To,X,Cur1).

dmsh
()
Ответ на: комментарий от runtime

> Совершенно верно. Но если магия нужна, почитай про CLP (Constraint Logic Programming) у Братко.

Хотя не, может конкретно эту задачу в таком виде и не решишь, но всё равно почитай.

runtime ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.