Компактное написание функциональной записи - PullRequest
6 голосов
/ 20 января 2020

Написание функциональных обозначений часто довольно дорого с точки зрения использования вспомогательного пространства. Это особенно важно для канонической записи списков.

Сначала рассмотрим размер вывода: тогда как для обычной записи ignore_ops(false) требуется как минимум 2n + 1 символов для списка длины n как в [1,2,3], каноническое письмо требует как минимум 7n + 2 как в '.'(1,'.'(2,'.'(3,[]))). (Добавлено :) Нет способа изменить вывод, так как он определен так, однако, есть достаточно возможностей для улучшения при записи:

А теперь рассмотрим вспомогательное пространство, необходимое записать вывод: Для написания списков в квадратных скобках не требуется никакого вспомогательного пространства, пропорционального длине списка. Наивное каноническое письмо требует пространства, пропорционального длине списка, чтобы представить стек отступов.

Как написать список канонически без этих накладных расходов?


Вот простой тест чтобы проверить, что происходит в вашей системе.

Во-первых, уменьшите максимальный размер виртуальной памяти, чтобы сократить время ожидания, у меня работает 180M-i sh.

$ ulimit -v -180000

С

nat_sx(N0, s(X)) :-
   N0 > 0,
   N1 is N0-1, nat_sx(N1,X).
nat_sx(0, 0).

?- open('/dev/null',write,Null),
   length(_,I), N is 10^I, nat_sx(N,SX),
   ( Res=unwritten ; write_canonical(Null,SX) ).

SICStus и SWI теперь прерываются в write_canonical(Null, SX). Ожидается, что они скорее прервутся в какой-то момент в nat_sx/2. Прямое сравнение для списков невозможно, так как SWI write_canonical/1 всегда использует квадратные скобки.

1 Ответ

5 голосов
/ 21 января 2020

Просто обработайте '.'( как открывающую скобку, ,'.'( - как запятую и увеличьте число целых чисел закрывающих скобок, которые будут выводиться в конце, как закрывающую скобку.

Таким образом O (1) вспомогательное пространство.

...