Манипуляции со списком - PullRequest
0 голосов
/ 02 марта 2011

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

list([]).


test([],_,_).                   
test([Child|List],B,C) :-
   append([Child],B,C),
   test(List,B,C).  

testme :-
        list(Final),
        test([1,2,3],Final,Result),
        write(Result).  

Функциональность, которую я требую из этого кода, чтобы Result был обратным списку ввода. Когда я прослеживаю этот код, я нашел обратный список ввода в C, но он не возвращается.

Я знаю, используя функцию reverse, я могу легко найти реверс списка, но меня интересует не поиск реверса, а понимание этого кода и работа пролога. Поэтому, пожалуйста, может кто-нибудь сказать мне, где я не прав и какие изменения необходимы в этом коде для правильной работы.

Ответы [ 2 ]

1 голос
/ 02 марта 2011

Сначала посмотрим, почему ваш код не работает.

test([],_,_).                   
test([Child|List],B,C) :-
   append([Child],B,C),
   test(List,B,C). 

Вы пытались определить рекурсивный предикат с двумя предложениями.Аргументами этого предиката являются: список ввода (1), промежуточный список (2) и конечный результат (3).

Таким образом, ваше первое предложение неверно.Предположим, что ваш входной список - просто пустой список.Результатом должен быть пустой список.Но в первом предложении вы оставляете третий аргумент как есть.Либо оно уже было связано с somenthing (в данном случае бесполезно), либо оно было неограниченным, и поэтому оно останется таким.

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

Вот ваш предикат test / 3, модифицированный для работы так, как вы ожидаете:

test([],List,List).
test([Child|List],B,D) :-
   append([Child],B,C),
   test(List,C,D). 

Теперь первое предложение просто объединяет второй и третий аргумент.Итак, в нашем первом тестовом примере (пустой входной список) напомним, что второй аргумент также был пустым списком, поэтому третий аргумент также будет пустым списком => правильный.

Теперь для рекурсивного предложения.Он возьмет первый элемент списка ввода и добавит его в промежуточный список, а также объединит его по новой переменной.Теперь мы переходим к шагу рекурсии, но теперь мы используем этот список (C) в качестве промежуточного списка.Это, при рекурсии, создаст список вывода, теперь связанный с D. Это то, что мы используем в качестве вывода.

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

test([],List,List).
test([Child|List],B,C) :-
   test(List,[Child|B],C).
0 голосов
/ 02 марта 2011

Правила Пролога могут только «возвращать» значения (поскольку на самом деле нет различия между параметрами и возвращаемыми значениями), объединяя их с их аргументами.Предполагая, что вам требуется операция reverse на основе аккумулятора, вам потребуется три параметра для test, и она должна действовать так, как если бы она была записана как:

test(A, B, C) :- reverse(A, A2), append(A2, B, C).

Наличие неявной операции добавления в test облегчит написание рекурсии.Также обратите внимание, что вы можете написать append([A], B, C) как C = [A | B] (или заменить C на [A | B]).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...