LINUX.ORG.RU

[swi-prolog] проблема со списками


0

1

Задание по прологу: Составить процедуру вставки в словарь, реализуемый линейным списком, элемента вида (строка, целое), где строка - ключ, целое - значение. Реализуемое отображение I:N. Контролировать, чтобы не было элементов с одинаковыми ключами. Пишу на Swi-prolog.

 :- initialization(goal).

goal :-
  new(Dir, directory('.')),
  new(Frame, frame('Select file')),
  new(Browser, browser),
  new(Dialog, dialog),
  send(Dialog, append(button('Open', message(@prolog, procfile, Browser?selection?key)))),
  send(Dialog, append(button('Quit', message(@prolog, halt)))),
  send(Browser, members(Dir?files)),
  send(Frame, append(Browser)),
  send(Dialog, below(Browser)),
  send(Frame, open).

procfile(Fname) :-
	see(Fname),
	read_list(List),
	addwordf(List,List1),
	write(Fname,List1),
	seen(Fname).
	
read_list(List) :-
  (
    at_end_of_stream ->
      List = [];
      read(Pair), read_list(List1), List = [Pair | List1]
  ).	

	
addwordf(List, List1) :-
	new(D, dialog('Word adding')),
	new(Txt1, text_item(value)),
	new(Txt2, text_item(key)),
	send(D, append, Txt1),
	send(D, append, Txt2),
	send(D, append, button('Add', message(@prolog, wordadd, prolog(List), Txt1?selection, Txt2?selection, prolog(List1)))),
	/*проблема, скорее всего, здесь, т.к. если передавать List1 как аргумент от prolog, его потом нельзя изменить (или я что-то неправильно делал)*/
	send(D, open).

wordadd([V/K | [V1/K1 | Tail ] ], Value, Key, TempList) :-
	TempList1 = [TempList | V/K],
	(
	    Key=:=K -> 
		   new(Der, dialog), 
		   send(Der, append, text('program is fucked up because of your key')),
		   send(Der, open);
	
		(
			Key>K -> 
			    wordadd([V1/K1 | Tail], Value, Key, TempList1);
				List1 = [TempList1 , Value/Key | Tail],
				TempList = TempList1
		)
	).
	
showResult(F) :-
	new(D, dialog('RESULT')),
	  new(B, button('Exit', message(D, destroy))),
	  new(V, view(F)),
	  send(D, append(B)),
	  send(D, append(V)),
	  send(V, load(F)),
	 send(D, open).

По прологу нуб, пишу вторую программу. Помогите исправить код, или хотя бы приведите пример кода со вставкой элемента в середину списка.


Ответ на: комментарий от anonymous

заменил проверку Key=:=K на проверку с member - проблема не в этом.

okay
() автор топика

Sorry, я бы опять помог, но свободное время появится только на выходных.

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

Мне лень доделывать до конца, поэтому вот набросок:

goal :-
  new(Dir, directory('.')),
  new(Frame, frame('Select file')),
  new(Browser, browser),
  new(Dialog, dialog),
  send(Dialog, append, button('Open', message(@prolog, procfile, Browser?selection?key))),
  send(Dialog, append, button('Quit', message(@prolog, halt))),
  send(Browser, members(Dir?files)),
  send(Frame, append, Browser),
  send(Dialog, below, Browser),
  send(Frame, open).

procfile(Fname) :-
	write(Fname), nl, flush_output,
	see(Fname), read_list(List), seen,
	write(List), nl, flush_output,
	addwordf(List).

read_list(List) :-
  (
    at_end_of_stream ->
      List = [];
      read(Pair), read_list(List1), List = [Pair | List1]
  ).	
	
addwordf(List) :-
	new(D, dialog('Word adding')),
	new(Txt1, text_item(key)),
	new(Txt2, text_item(value)),
	send(D, append, Txt1),
	send(D, append, Txt2),
	send(D, append, button('Add', message(@prolog, wordadd, prolog(List), Txt1?selection, Txt2?selection))),
	send(D, open).

wordadd(ListIn, Key, Value) :-
	(
		member(Key/_, ListIn) ->
		ListOut = ListIn;
		ListOut = [Key/Value | ListIn]
	),
	write(ListOut), nl, flush_output.

Файл данных:

key1 / val1.
key2 / val2.
key3 / val3.
key4 / val4.

Основные проблемы, которые были у тебя:

  • неправильное использование предикатов (RTFM!), например, seen не принимает параметров;
  • вызов предикатов xpce сразу возвращает true, поэтому применение, скажем addwordf(List,List1), write(Fname,List1) бессмысленно: addwordf просто создаст окно ввода и успешно завершиться, но не будет ждать пока List1 будет заполнен; следовательно, write получит кукиш с маслом вместо List1;
  • непонимание списков: TempList1 = [TempList | V/K] сделает совсем не то, что ты думаешь (оно создаст список из 2 элементов, но не добавит V/K в конец как ты хотел); здесь могу посоветовать только RTFM и практиковаться на несложных примерах (без XPCE'шного GUI);
  • last but not least: отсутствие flush_output не повышает понимание выхлопа программы

Also, тебе действительно нужен ГУЙ? В любом случае, предикаты сперва нужно отлаживать безо всякой гуйни, и лишь потом добавлять окошки.

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