Во-первых, у вас есть одноэлементная переменная X
здесь:
extend(X, [], []).
Было бы лучше сказать extend(_, [], [])
, потому что вы никогда больше не обращаетесь к X. Важно понять, почему это так. В Прологе все действие происходит из-за отношений, в которых находятся переменные. Если переменная появляется только в одном месте, она не участвует ни в каких отношениях, поэтому ее следует заменить на _
. (Если вы делаете такое изменение, а код кажется бессмысленным, остановитесь и изучите его, потому что это всегда означает, что вы что-то неправильно поняли.)
Во-вторых, is/2
для оценки арифметических выражений. В этом нет математики: Firstxss is [Firstxss,_|X]
, поэтому вы перепутали это с =
. Это действительно двойной удар, потому что =
действительно не означает присвоение в Прологе, это означает унификация . Так что в Прологе нет реальной ситуации, когда у вас будет X = X+1
или что-то подобное, что именно то, что вы делаете здесь, пытаясь повторно использовать переменную для различных целей.
Что означает Firstxss
в этом пункте? Похоже, что это первый элемент во вложенном списке во втором аргументе в заголовке: другими словами, если вы вызвали extend(g, [[e], [b, c, f], [k, h]], Yss)
, то Firstxss = e
. Значение Firstxss
никогда не может измениться . Это может быть восстановлено только в рекурсивном вызове. Поэтому, когда вы сразу говорите Firstxss is [Firstxss,_|X]
, то, что видит Пролог b = [b,_|<another var>]
. Это не объединяет, и ваш предикат терпит неудачу в этой точке. Скажи это как-то продвинуто. Вы делаете ту же ошибку в следующей строке с Yss
.
Это помогло бы подумать о вашей проблеме в отношениях. У вас тоже неверный базовый вариант. Каков ваш базовый случай? Это тот случай, когда вы достигли конца списка, и что вам делать? Добавить X. Итак, это ваш базовый случай:
extend(X, [], [X]).
Теперь подумайте, что вы хотите сделать в других случаях: у вас есть голова и хвост. Как вы продлите? Вы расширяете хвост, и ваш результат - голова, прикрепленная к удлиненному хвосту. Попробуйте сами написать это предложение, это не так сложно!
Как только вы это сделаете, механизм расширения вложенных списков прост: вы проверяете голову, чтобы убедиться, что это список. Если это так, вернитесь на голову и хвост! Вот так:
extend(X, [Y|Ys], Result) :-
(is_list(Y) -> extend(X, Y, Y1) ; Y1 = Y),
... % use Y1 as Y in building the result