2015-01-16 4 views
0

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

К тому времени я создал функцию, которая Concat элементы списка списков:

concat([[]|L],L3):- concat(L,L3). 
concat([[Head|L1]|L2],[Head|L3]):- concat([L1|L2],L3),!. 

Теперь, что мне нужно знать, как сделать возвращаемое значение этой функции и сравнить его с list (второй аргумент функции).

+0

Пролог не имеет * функций * с * возвращаемыми значениями *. В Prolog есть * предикаты *, которые определяют * отношения * между его аргументами. Немного непонятно, о чем вы просите. – lurker

+0

Что происходит, если 'L' является' [] '? – lurker

+0

concat ([], []). Но я думаю, что это не обязательно, потому что я нарушаю рекурсию с помощью!. – Saturnino

ответ

0

Это один подход, который позволит до одного элементы в подсписке, но не пустой подсписок:

concat([[L]], [L]). 
concat([[H],L|T], [H|R]) :- concat([L|T], R). 
concat([[H1,H2|T]|LT], [H1|RT]) :- concat([[H2|T]|LT], RT). 

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

Если у вас есть переменная, Y, уже инстанцированный, и вы хотите знать, если это является результатом конкатенации список списков, LL, вы просто запрос:

concat(LL, Y). 

Это будет true если Y является объединением списка LL и false если нет. Вам не нужно «возвращать и сравнивать» (как, например, в C, можно сказать, concat(LL) == Y, или concat(LL, X); if (X == Y)...). Это связано с тем, что concat - отношение , определенное между двумя аргументами, и определяет, можно ли сделать запрос true, следуя указанным правилам (предложения предиката).

Если вы уже получили результат и хотите, чтобы определить, является ли это unifiable другой переменной, Z, то вы можете сказать:

concat(X, Y), Y = Z. 

Обратите внимание, что в Прологе concat(X, Y) == Z не является правильным, чтобы определить, является ли результат предиката равна Z, потому что это не функция, которая возвращает значение.

+0

Это прекрасно, просто точка. Я думал об этом вчера, и я прихожу примерно к тому же конкусиону, что и вы. Но я добавил перерыв "!" после concat ([[H], L | T], [H | R]): - concat ([L | T], R). чтобы заставить предикат вернуть только одно истинное или ложное. И я создал a: compare (X, Y): - concat (X, C), C = Y., просто чтобы узнать, какой второй аргумент будет соответствовать первому. Например: сравните ([[1,2], [3,4]], L). должен быть L = [1,2,3,4]. – Saturnino

+0

@ Сатурнино, я, как правило, оставляю вырезать, если это абсолютно необходимо. Если вы включите разрыв в этом случае, это связано с тем, что вы пытаетесь заставить предикат вести себя более императивно (дайте ему вход и получите один вывод). Но без разрыва такие запросы, как 'concat (L, [1,2,3]).', Покажут вам все возможные значения 'L', которые объединяются в' [1,2,3] '. С сокращением на месте этот запрос не даст всех правильных ответов, поскольку они были обрезаны срезом. Это проблема с использованием разрезов: они могут устранить возможные альтернативные решения. Используйте с осторожностью. – lurker

+0

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

0

Пролог не имеет функций или возвращает значения в смысле процедурного языка программирования. Он имеет предикаты, которые утверждают, что отношения. Он имеет условия, которые включают в себя переменные который поставляется с некоторыми стриктур:

  • Все переменные являются локальными и
  • переменной, когда присваивается значение, перестает быть переменной. Вот почему это называется унификация.

Так ....

Если вы хотите, предикат, который будет принимать два списка и производить их конкатенацию, вам необходимо пройти его третьей переменной. Вы можете вызвать его так:

concat([a,b],[c,d],X). 

, который утверждает, что X является конкатенация [a,b] и [c,d]. Механизм вывода Prolog затем оценит правду или фальшь утверждения.

В большинстве рекурсивных проблем есть несколько особых случаев и более общий случай. Реализация такого предиката concat/3 может выглядеть примерно так (аннотированный, чтобы объяснить, что он делает).

  • Во-первых, у нас есть один специальный (и заканчивающуюся) случай: Если список левый пуст, конкатенация просто список правой.

    concat ([], Bs, Bs).

  • Далее, у нас есть один общий случай: если список левосторонний не пусто, мы должны предварять его к concatentation, что мы строим

    CONCAT (а затем рекурсия вниз.) ([A | As], Bs, [A | Cs]): - concat (As, Bs, Cs).

Это все, что есть два. Вы также заметите, что это двунаправлено: он также счастлив разделить списки отдельно.Призывая это так:

concat(Prefix , Suffix, [a,b,c,d]). 

будет, по возвратам, производить все возможные способы, которые [a,b,c,d] можно разделить на приставку и суффикс:

Prefix Suffix 
--------- --------- 
[]  [a,b,c,d] 
[a]  [b,c,d] 
[a,b]  [c,d] 
[a,b,c] [d] 
[a,b,c,d] [] 
+0

Спасибо за ваш ответ, но это не то, что я ищу. – Saturnino

0

Вам просто нужно базовый случай

concat([],[]). 
concat([[]|L],L3):- concat(L,L3). 
concat([[Head|L1]|L2],[Head|L3]):- concat([L1|L2],L3). 

Он также работает для пустых (суб) списков. Я удалил бесполезный разрез.

+0

ОП указывает, глубоко погруженный в один из своих комментариев на свой пост, что он не хочет, чтобы пустые подсписчики преуспели. – lurker

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