Описание функций управления средой HomeLisp и диалогом с пользователем

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

Некоторые из функций, рассматриваемых в этом разделе, недоступны при работе WEB-компоненты или при работе с библиотекой HomeLispLib.exe (этот факт отмечается в детальном описании таких функций). Те функции, которые реализованы только в ядре 11 или 13 помечены значками (11) и (13) соответственно.

Запись и сохранение состояния

Одной из новых возможностей 13-го ядра является возможность сохранения/восстановления полного состояния Лисп-машины в двоичном файле.

При сохранении состоянии в файл попадает полное состояние Лисп-машины за исключением открытых файлов (двоичные объекты, диалоги, графические окна с их содержимым и все введенные пользовательские функции). Очень существенным отличием этого способа сохранения состояния является то, что можно сохранить циклические списочные структуры. Традиционный способ сохранения состояния (с помощью функции WRS) такую возможность не обеспечивает.

Сохранение/восстановление состояния обеспечивается функцией WRITEIMAGE и псевдофункцией READIMAGE. Рестарт системы может быть выполнен с помощью псевдофунции RESTART.

Имя функции Тип функции К-во аргументов Тип аргументов Выполняемое действие
  ASK SUBR 1 STRING Выводит диалоговое окно (InputBox), c текстом приглашения, равным значению атома-аргумента. Возврашает введенный пользователем текст в виде атома типа STRING.
  ASSERT (13) FSUBR 1 ANY Вычисляет условие и, при истинности, останавливает выполнение. Работает только в режиме отладки.
  ASSOLIST (11) SUBR 1 (необязательный) STRING Строит снимок ассоциативного списка.
  CLS SUBR 0 - Программно очищает область вывода
  DEBUG (13) FSUBR 1 ANY Вызывает интерактивный отладчик
  DUMP* FSUBR 1 (необязательный) STRING Включает режим дампирования, направляя его в файл с полным именем, заданным аргументом
  ECHO SUBR 0 - Включает/выключает режим эха
  EXIT SUBR 1 (необязательный) STRING Завершает выполнение с итоговым сообщением
  INPUT SUBR 1 STRING Преобразует значение аргумента в S-выражение. Это S-выражение возвращется в качестве результата.
  OBJLIST SUBR 1 (необязательный) STRING Строит снимок списка объектов.
  OUTPUT SUBR 1 ANY Выводит значение своего аргумента в виде строки.
  PHIDE SUBR 1 ANY Скрывает прогресс-бар.
  PSHOW SUBR 1 ANY Отображает прогресс-бар.
  RDS SUBR 1 (необязательный) STRING Читает все S-выражения из файла с именем, заданным аргументом; Если аргумент опущен - вызывается диалог OPEN
  READ SUBR - - Читает S-выражение, вводимое пользователем во время выполнения программного кода
  READIMAGE (13) Псевдофункция 1 (необязательный) STRING Восстанавливает состояние Лисп-машины из файла-образа, созданного функцией WRITEIMAGE
  RESTART (13) Псевдофункция - - Сброс состояния Лисп-машины
  RDS SUBR 1 (необязательный) STRING Читает все S-выражения из файла с именем, заданным аргументом; Если аргумент опущен - вызывается диалог OPEN
  SAY SUBR 1 STRING Выводит диалоговое окно (MessageBox) с текстом сообщения, равным значению аргумента.
  STAT FSUBR 0 - Включает режим статистики
  TRACE FSUBR 1 Атом Включает режим трассировки для функции, имя которой задано атомом-аргументом
  UNDUMP* FSUBR 0 - Выключает режим дампирования
  UNSTAT FSUBR 0 - Выключает режим статистики
  UNTRACE FSUBR 1 Атом Выключает режим трассировки для функции, имя которой задано атомом-аргументом
  VARLIST (13) SUBR 1 (необязательный) STRING Выводит таблицу активных переменых
  WRITEIMAGE (13) SUBR 1 (необязательный) STRING Записывает состояние Лисп-машины в двоичный файл с именем, заданным аргументом; Если аргумент опущен - вызывается диалог "SAVE AS"
  WRS SUBR 1 (необязательный) STRING Записывает все S-выражения (кроме циклических) в текстовый файл с именем, заданным аргументом; Если аргумент опущен - вызывается диалог "SAVE AS"
ASK  

Функция ASK предназначена для организации примитивного диалога с пользователем (во время выполнения программы на Лиспе). Функция ожидает единственный аргумент - атом. Выводится диалоговое окно (INPUT BOX), в область приглашения которого попадет значение атома-аргумента. Пользователь вводит ответ в область ввода и нажимает кнопку "Принять". Ответ пользователя превращается в атом с индикатором STRING и этот атом возвращается в качестве результата функции.

Так, если ввести: (ask "Введите что-нибудь"), то будет выведено диалоговое окно:

Если далее пользователь введет в область ввода текст или S-выражение, то функция вернет ввод пользователя в виде атома с индикатором STRING. Если пользватель нажмет кнопку "Cancel" ("Отказ"), то результатом будет пустая строка.

Разработчик обращает внимание на то, что если требуется ввести S-выражение, то результат вызова ASK следует передать на вход функции INPUT, описываемой ниже. Функция недоступна при работе WEB-компоненты.

ASSERT  

Функция ASSERT (реализованная только в 13-й редакции ядра HomeLisp),предназначена для работы в диалоговом отладчике среды разработки. Эта функция недоступна в WEB-компоненте. При работе с библиотекой HomeLispLib.exe или в составе EXE-файла функция игнорируется (сразу же возвращает Nil).

Функция принимает S-выражение. Если при вызове функции активен диалоговый отладчик, то заданное S-выражение вычисляется в текущем контексте. Если результат оказывается отличным от Nil, выполнение приостанавливается, и пользователь получает возможность увидеть значение переменных, задать/сменить точки останова и т.д.

Если же при вызове функции отладчик неактивен, то функция ASSERT сразу же возвращает Nil. Рассмотрим пример:


(defun f (x &aux i n) (for i 20 40 ((setq n (fact i)) 
                                    (assert (>= n x)))
                      )            
)

==> f

(f 100000000000000000000000000)

==> 40

Здесь в теле функции последовательно вычисляется значение факториалы целых от 20 до 40. Если вызвать эту функцию из IDE, то цикл выполнится до конца (как это видно из приведенной врезки). Если же выполнить эту функцию в автоматическом режиме под отладчиком, то пользователь увидит:


Нетрудно убедиться, что выражение, заданное в ASSERT станет истиным, когда i > 25, что и подтверждается информацией, отображенной в окне "Лексический контекст".

ASSOLIST  

Функция ASSOLIST строит снимок ассоциативного списка (на момент вызова функции). При вызове может быть указан один необязательный аргумент (типа STRING). В снимок включаются все переменные из ассоциативного списка, в именах которых содержится (в любой позиции) значение аргумента. Если аргумент опущен - строится снимок всего ассоциативного списка.

При работе в Web-компоненте снимок представляет собой отдельный html-файл, сылка на который сохраняется в течение сеанса пользователя. Так, если выполнить в Web-компоненте следующий код:


(setq a 111)

(defun f (x) (prog nil (assolist) (* x x)))

то снимок ассоциативного списка будет иметь вид:

Здесь хорошо видно, что переменная a (созданная на верхнем уровне вызовом SETQ) является глобальной переменной, тогда как переменная x является параметром функции и при выходе из функции будет уничтожена.

В составе библиотеки HomeLispLib.Exe снимок ассоциативного списка в виде таблички направляется в область вывода (аналогично выходным данным функции PRINT). Так, в составе скриптового движка Conlisp, снимок ассоциативного списка отображается так:

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


(setq a 222)

==> 222

(defun f (x y) (prog nil (assolist) (return (* x y))))

==> f

(f 5 6)

+-----------------+---------+-----------+
| Имя переменной  | Тип     | Значение  |
+-----------------+---------+-----------+
|a                |Глобал.  |222        |
|x                |Параметр |5          |
|y                |Параметр |6          |
+-----------------+---------+-----------+

==> 30
CLS  

Эта функция не имеет аргументов. Ее выполнение заключается в очистке области вывода. Этого же эффекта можно добиться, нажав соответствующую кнопку или выполнив пункт контекстного меню "Очистить область вывода". Функция недоступна при работе WEB-компоненты, а также библиотеки HomeLispLib.exe.

DEBUG  

Функция DEBUG (реализованная только в 13-й редакции ядра HomeLisp), доступна только при работе в IDE. Функция активизирует интерактивный отладчик (описанию отладчика посвящен отдельный документ).

Функция DEBUG принадлежит к типу FSUBR и принимает один необязательный аргумент - отлаживаемое S-выражение. Если аргумент не задан, то выражение можно задать уже в отладчике (в окне "Стартовое S-выражение").

DUMP*  

Функция DUMP* (отсутствующая у Лаврова и Силагадзе) позволяет пользователю проследить весь процесс вычисления S-выражения на весьма детальном уровне. Использование странного, на первый взгляд, окончания имени функции (*) имеет на самом деле вескую причину. В Лиспе принято, что функция, имя которой оканчивается буквой p, является предикатом (функцией, возвращающей логическое значение). Поскольку описываемая функция предикатом не является, использование слова DUMP для ее именования нарушило бы традицию Лиспа.

Функция DUMP* может иметь единственный параметр строкового типа. Он интерпретируется как имя выходного файла (может присутствовать буква диска и слэши). Если параметр не содержит буквы диска и слэшей, то он интерпретируется как имя файла в текущей директории. Если присутствует расширение, то оно заменяется на ".dmp". Если функция DUMP* вызвана без параметров, то отображается окно диалога и пользователь может выбрать выходной файл. После того, как выходной файл выбран, его имя отображается в шестой (самой правой) панели статус-бара главного окна. Теперь при вводе любого S-выражения результаты всех промежуточных вычислений будут выведены в выбранный файл; файл каждый раз переоткрывается в режиме "APPEND".

Включить дампирование можно и нажатием кнопки (выбором пункта меню). В этом случае появится окно диалога и пользователь может выбрать файл. При нажатии кнопки "Отказ" режим не включается. Результаты дампа можно просмотреть, не выходя из среды разработки. Для этого служит соответствующая кнопка и пункт меню.

Естественно, что процесс дампирования очень сильно увеличивает время вычислений. Некоторое сходство с режимом дампирования имеет режим трассировки, но он отслеживает только обращения к одной или нескольким функциям пользователя, тогда как в дамп попадают все вызовы встроенных функций (в т.ч. и недоступных непосредственно пользователю) и все вызовы функций, заданных пользователем. Кроме того, протокол трассировки попадает не в отдельный файл, а в область вывода.

Рассмотрим пример. Пусть значение переменной x равно 1, значение переменной y равно 2, и значение переменной z равно 3.Ниже приводится ход вычисления выражения (+ x y z).


.EVAL вход:  (PLUS x y z)
..CAR вход: A= (PLUS x y z)
..CAR выход: Рез= PLUS
..CDR вход: A= (PLUS x y z)
..CDR выход: Рез= (x y z)
..APPLY вход: A1= PLUS A2= (x y z)
...EVFUN вход: A1= PLUS A2= (x y z)
...
... Ассоциативный список:
...
...  3  ->  (z . 3)
...  2  ->  (y . 2)
...  1  ->  (x . 1)
...
....LIST вход: A= (x y z)
.....CAR вход: A= (x y z)
.....CAR выход: Рез= x
.....EVAL вход:  x
......EVATOM вход:  x
......EVATOM выход:  1
.....EVAL выход:  1
.....CDR вход: A= (x y z)
.....CDR выход: Рез= (y z)
.....CAR вход: A= (y z)
.....CAR выход: Рез= y
.....EVAL вход:  y
......EVATOM вход:  y
......EVATOM выход:  2
.....EVAL выход:  2
.....CDR вход: A= (y z)
.....CDR выход: Рез= (z)
.....CAR вход: A= (z)
.....CAR выход: Рез= z
.....EVAL вход:  z
......EVATOM вход:  z
......EVATOM выход:  3
.....EVAL выход:  3
.....CDR вход: A= (z)
.....CDR выход: Рез= NIL
....LIST выход: Рез= (1 2 3)
....PLUS вход: A= (1 2 3)
.....CAR вход: A= (1 2 3)
.....CAR выход: Рез= 1
....PLUS пром. рез=1
.....CDR вход: A= (1 2 3)
.....CDR выход: Рез= (2 3)
.....CAR вход: A= (2 3)
.....CAR выход: Рез= 2
....PLUS пром. рез=3
.....CDR вход: A= (2 3)
.....CDR выход: Рез= (3)
.....CAR вход: A= (3)
.....CAR выход: Рез= 3
....PLUS пром. рез=6
.....CDR вход: A= (3)
.....CDR выход: Рез= NIL
....PLUS выход: Рез= 6
...EVFUN выход:  6
..APPLY выход:  6
.EVAL выход:  6

В дампе отчетливо видны основные стадии вычисления. Сначала выделяется голова списка; этот атом интерпретируется как имя функции (PLUS). Из списка аргументов строится новый список, при этом, каждый атом заменяется своим значением (они берутся из ассоциативного списка). Вновь построенный список дается на вход функции PLUS. Функция PLUS вычисляет сумму элементов списка значений аргументов ("чинит карандаш", пока он не исчерпается). Результат вычисления по цепочке вызовов возвращается пользователю (попадает в область вывода).

ECHO  

Функция ECHO управляет режимом дублироания введенного S-выражение в область вывода. Включается режим вызовом функции (ECHO T), а выключается вызовом (ECHO NIL). Когда режим эха включен, введенное пользователем S-выражение дублируется в области вывода; результат вычисления выводится ниже после комбинации "==>". Если режим эха выключен, то в области вывода печатется только результат вычисления. Состояние режима эха (Вкл/Выкл) выводится в шестой (самой правой) панели статус-бара. Режимом эха можно управлять и с помощью меню или тулбара - имеется пункт меню и командная кнопка. Однократное нажатие на кнопку меняет статус эха на противоположный. Функция недоступна при работе WEB-компоненты, а также при работе в составе EXE-файла и при вызове из библиотеки HomeLispLib.Exe.

EXIT  

Функция EXIT завершает сеанс работы. Программа HomeLispIde.Exe завершается. Функция может иметь аргумент (обязательно типа STRING). Если аргумент задан, текст строки выдается в диалоговом окне в качестве "прощального сообщения" - (EXIT "Прощай!..") Для завершения сеанса пользователь может также нажать кнопку "Выход" или щелкнуть по соответствующему пункту главного меню. Функция недоступна при работе WEB-компоненты.

INPUT  

Функция INPUT ожидает единственный аргумент-атом строкового типа. Функция рассматривает значение атома (строку символов) как S-выражение и переводит его во внутреннюю Лисп-форму. Полученное S-выражение функция INPUT возвращает в качестве результата. Вот как это выглядит:

(input "(+ 3 4)")

==>  (PLUS 3 4)

(eval (input "(+ 3 4)"))

==>  7

(input "(a . b)")

==>  (a . b)

(input "nil")

==>  NIL

(input "(a b c)")

==>  (a b c)

(eval (input "(a b c)"))

Атом "a" не имеет значения (не связан).
==>  ERRSTATE

(input '(a b c))

INPUT: параметр - не атом
==>  ERRSTATE

(input 'a)

INPUT: параметр должен иметь тип STRING
==>  ERRSTATE

(input ")(")

Нарушен баланс скобок или неверна скобочная структура
==>  NIL

Пусть читатель обратит внимание, что описываемая функция не вычисляет выражение, а только переводит его во внутреннюю списковую форму. Если к результату INPUT применить EVAL, то результат будет вычислен (точнее, будет выполнена попытка его вычисления - как это показано на врезке).

OBJLIST  

Функция OBJLIST принимает единственный необязательный аргумент (типа STRING) и строит снимок списка объектов (атомов), в именах которых в любой позиции встречается значение аргумента. Если аргумент опущен, то строится снимок всех объектов. Следует отметить, что если очередной объект есть строка, то проверка осуществляется с учетом регистра. Для прочих атомов проверка выполняется без учета регистра.

При работе в Web-компоненте снимок списка объектов формируется в отдельном html-файле (который сохраняется до конца сеанса пользователя). Вид списка объекта приводится ниже:

При работе со скриптовым движком Conlisp.exe список имеет вид:

Здесь создано графическое окно ww, а затем запрошен список объектов, в именах которых содержится комбинация ww. Видно, что таких атомов оказалось всего два: окно и строка "ww" (из вызова (objlist "ww"). Пусть читатель обратит внимание на то, что у строки установлен только стандартный флаг STRING, тогда как у атома ww наряду со стандартным флагом WINDOW, имеется список нестандартных свойств (характеристики окна).

Совершенно аналогично выглядит результат вызова функции OBJLIST в среде IDE:


(grwCreate 'ww 200 200 "Графическое окно" _WHITE)

==> ww

(objlist "ww")
+-----------------------------------------+-----------------+-----------------+
| Имя атома                               | Станд. флаги    | Доп. флаги      |
+-----------------------------------------+-----------------+-----------------+
|"ww"                                     |STRING;          |                 |
|ww                                       |WINDOW;          |(width 200 height|
|                                         |                 | 200 title "Графи|
|                                         |                 |ческое окно" back|
|                                         |                 |color &HFFFFFF WI|
|                                         |                 |NHANDLE 1)       |
+-----------------------------------------+-----------------+-----------------+

==> T

OUTPUT  

Функция OUTPUT ожидает единственный аргумент произвольного типа (атом или список) и выводит его значение в виде строки. Функция OUTPUT позволяет сохранить внешнюю (печатную) форму S-выражения в виде строки. Функция OUTPUT предназначена в основном для использования в диалоговых программах. Следует отметить, что в отличие от функций PRINT/PRINTS, Функция OUTPUT возвращает строку и дополнительно ничего не выводит в область вывода (при использовании в IDE). Ниже приводятся примеры вызовов OUTPUT:


(output (cdr '(1 2 3)))

==> "(2 3)"

(input (output (cdr '(1 2 3))))

==> (2 3)

Видно, что функция OUTPUT в некотором смысле является обратной по отношению к INPUT: результат OUTPUT может быть из строковой формы преобразован в форму S-выражения посредством INPUT.

PHIDE  

Функция PHIDE не имеет аргументов. Вызов этой функции скрывает прогресс-бар, отображенный ранее функцией PSHOW.

PSHOW  

Функция PSHOW имеет два аргумента. Первый аргумент должен быть числом в интервале [0 - 100]. Второй аргумент (необязательный) должен быть строкой разумной длины. Вызов функции PSHOW вызывает отображение на экране прогресс-бара. При этом первый параметр задает процент выполнения процесса, ход которого показывает прогресс-бар. Второй параметр задает текст, который отображается над прогресс-баром. Если второй параметр опущен, то в области текста отображается значение первого параметра. Прогресс-бар, отображенный вызовом (pshow 43 "Немного подождите...") выглядит так:

Скрыть прогресс-бар можно вызовом функции PHIDE.

RDS  

Функция RDS предназначена для чтения S-выражений из файла. Вызвать функцию RDS можно двумя способами: без аргументов и с единственным аргументом (значение которого должно быть строкового типа).

В первом случае будет вызвано стандартное окно диалога выбора файла (с расширением .lsp). Если пользователь выбирает файл и нажимает кнопку "Принять", то из файла считываются и загружаются все S-выражения. S-выражения в файле могут быть записаны в свободном формате. При этом содержимое строки после пары символов "//" или ";;" считается комментарием и игнорируется.

Во втором случае проверяется, существует ли файл с именем, заданным значения аргумента. Имя может содержать букву диска. Если имя не содержит обратных слешей и буквы диска, файл будет искаться в текущей директории. При этом, если расширение файла задано отличным от .lsp, оно принудительно Заменяется на .lsp.

В случае успешной загрузки всех S-выражений из файла, в область вывода выводится сообщение об успешной загрузке файла, в противном случае выводится сообщение об ошибке. Функция RDS неявно вызывается при запуске HomeLisp с параметром имя автозагружаемой библиотеки. При работе WEB-компоненты функция позволяет загрузить данные только из рабочей директории авторизованного пользователя. Аргумент в этом случае является обязательным и не может содержать путь (диск и директорию).

READ  

Функция READ введена в HomeLisp для совместимости с существующими версиями Лиспа. Функция не требует параметров и обеспечивает чтение S-выражения, вводимого пользователем во время выполнения программы. Результатом функции является S-выражение, введенное пользователем. Функция READ имеет два отличия от описанной выше функции ASK:

  Функция READ возвращает не строку, а S-выражение (т.е. не требует последующего вызова функции INPUT);
  Функция READ не выводит диалогового окна, а ожидает ввода пользователя в области ввода (зависящей от режима выполнения).

При выполнении программы в IDE вызов функции READ выполнение программы прерывается, цвет области ввода становится белым, а вся область ввода окружается красной рамкой. Пользователь должен ввести S-выражение в область ввода и нажать ENTER. Функция не вернет управление до тех пор, пока пользователь не введет корректное S-выражение (со сбалансированными скобками). После возврата из функции READ цвет области ввода восстановится, а красная рамка исчезнет.

При выполнении программы в среде Conlisp.exe вызов READ устанавливает курсор в начало строки, следующей за текущей. Пользователь должен ввести S-выражение и нажать ENTER.

Если вызов функции READ встретился в коде, выполняющемся в среде Wlisp.exe, то функция возвращает Nil. Функция READ недоступна в WEB-компоненте и в составе EXE-файлов.

READIMAGE  

Псевдофункция READIMAGE (реализованная только в 13-й редакции ядра HomeLisp) обеспечивает восстановление состояния Лисп-машины из образа, созданного вызовом функции WRITEIMAGE. Слово "псевдо" в названии фигурирует не случайно: READIMAGE не является частью ядра HomeLisp. Если при работе IDE ввести в область ввода команду (READIMAGE), то откроется окно диалога Открыть и пользователь может выбрать файл-образ (*.hli). Если же ввести (READIMAGE "имя.hli"), то будет выполнена попытка восстановления состояния из заданного файла.

В обоих случаях состояние Лисп машины после восстановления не имеет ничего общего с состоянием машины до выполнения (READIMAGE), поэтому совершенно бессмысленно использовать вызов (READIMAGE) в программном коде (такая попытка вызовет ошибку Отсутствует функция READIMAGE.

Вместо того, чтобы вводить команду (READIMAGE), можно просто нажать кнопку "Загрузить" и в выпадающем списке типов файлов выбрать "Файлы образов *.hli".

Пользователю будет предложено подтвердить восстановление состояния. При подтверждении состояние восстанавливается. При этом все объекты Лиспа, созданные до восстановления, замещаются номыми.

RESTART  

Псевдофункция RESTART (реализованная только в 13-й редакции ядра HomeLisp) переводит Лисп-машину в состояние, которое она имела при старте сразу после загрузки функций стандартной библиотеки. Команду (RESTART) можно ввести только при работе с IDE. Честно говоря, разработчик сейчас сомневается, стоило ли открывать доступ к служебной функции RESTART, ведь достаточно просто достичь эффекта рестарта можно просто перезапустив IDE...

SAY  

Функция SAY предназначена выдачи сообщения пользователю во время выполнения программы на Лиспе. Функция ожидает единственный параметр-атом. Этот атом может иметь тип FIXED, FLOAT, STRING или BITS. Выводится стандартный message-box в область текста которого попадает значение аргумента. Так, если введено выражение (SAY &H112233), то пользователь увидит следующее:

Функция SAY всегда возвращает T. Функция недоступна при работе в составе WEB-компоненты.

STAT  

Функция STAT не требует аргументов. Эта функция включает режим статистики. При включенном режиме статистики после завершения вычисления входного выражения выдается количество обращений ко всем функциям системы. Включение режима статистики позволяет оценивать и анализировать сложность вычисления вводимых выражений. Статус режима статистики выводится в шестой (самой правой) панели статус-бара главного окна программы (Стат=Вкл/Выкл; по умолчанию режим выключен). Для включения режима статистики можно также использовать соответствующую кнопку панели инструментов или пункт главного меню. При успешном завершении функции STAT, она возвращает результат T.

Вот как выглядит результат применения режима статистики. Рассчитаем значение числа 20! двумя способами - с использованием рекурсивной процедуры fact_rec и с использованием итерационной процедуры fact_iter:


(defun fact_rec (x) (cond ((eq x 1) 1) (t (* x (fact_rec (- x 1))))))

==> fact_rec

(STAT)

==> T

(fact_rec 20)

==>  2432902008176640000

*** Статистика обращений ***
DIFFERENCE ...............  19
TIMES ....................  19
EQ .......................  20
FACT_REC .................  20
COND .....................  20


(defun fact_iter (x) (prog (r)
                       (setq r 1) 
                   L   (cond ((eq x 1) (return r)))
                       (setq r (* r x))
                       (setq x (- x 1))
                       (go l)
                     )
)

==> fact_iter

*** Статистика обращений ***
DEFUN ....................  1

(fact_iter 20)

==> 2432902008176640000

(fact_iter 20)

==> 2432902008176640000

*** Статистика обращений ***
FACT_ITER ................  1
PROG .....................  1
RETURN ...................  1
DIFFERENCE ...............  19
GO .......................  19
TIMES ....................  19
COND .....................  20
EQ .......................  20
SETQ .....................  39

Следует обратить внимание на то, что, будучи включенным, режим статистики выводит сведения о каждом вычисленном S-выражении на верхнем уровне (т.е. о каждом S-выражении, введенном пользователем). Так, в приведенном выше примере, задание новой функции fact_iter осуществляется вызовом функции DEFUN. Этот вызов тоже попадает в статистику.

Для выключении режима статистики служит "парная" функция UNSTAT, описываемая ниже.

TRACE  

Функция TRACE принимает один аргумент - имя функции типа EXPR, FEXPR или MACRO. Если функция, заданная аргументом TRACE, существует, то в качестве результата вычисления возвращается значение аргумента. В противном случае возвращается NIL. Вызов функции TRACE устанавливает у функции, заданной значением аргумента, флаг трассировки. Если теперь вызвать эту функцию, то перед печатью результата вычисления будет выведен протокол трассировки, включающий входную информацию каждого вызова трассируемой функции и результат вычислений. Рассмотрим, например, протокол трассировки рекурсивной функции вычисления факториала:


(defun fact_rec (x) (cond ((eq x 1) 1) (t (* x (fact_rec (- x 1))))))

==> fact_rec

(trace fact_rec)

==> fact_rec

(fact_rec 7)

Вход в функцию fact_rec Аргументы:  (7)
  Вход в функцию fact_rec Аргументы:  (6)
    Вход в функцию fact_rec Аргументы:  (5)
      Вход в функцию fact_rec Аргументы:  (4)
        Вход в функцию fact_rec Аргументы:  (3)
          Вход в функцию fact_rec Аргументы:  (2)
            Вход в функцию fact_rec Аргументы:  (1)
            Возврат из функции fact_rec Результат:  1
          Возврат из функции fact_rec Результат:  2
        Возврат из функции fact_rec Результат:  6
      Возврат из функции fact_rec Результат:  24
    Возврат из функции fact_rec Результат:  120
  Возврат из функции fact_rec Результат:  720
Возврат из функции fact_rec Результат:  5040

==> 5040

Для функций типа MACRO в дополнение к аргументам выводится результат макрорасширения. Трассировку удобно применять отладке сложных программ, - она по сути дела выводит "облегченный" вариант дампа выполнения. Для выключения трассировки служит "парная" функция UNTRACE, описываемая ниже.

UNDUMP*  

Функция UNDUMP* (звездочка в конце имени введена из-за нежелания нарушать традицию Лиспа - все, что оканчивается на p - предикат) выключает режим дампирования. Вместо явного вызова функции UNDUMP* можно нажать соответствующую кнопку панели инструментов или выбрать соответствующий пункт главного меню. Функция UNDUMP* всегда возвращает NIL

UNSTAT  

Функция UNSTAT выключает режим статистики. Функция всегда возвращает NIL. Вместо явного вызова функции UNSTAT можно нажать соответствующую кнопку панели инструментов или выбрать соответствующий пункт главного меню.

UNTRACE  

Функция UNTRACE выключает режим трассировки для фукнции, имя которой есть значение единственного аргумента UNTRACE. Функция возвращает имя функции, у которой выключается трассировка. Если функция, заданная аргументом UNTRACE, отсутствует, возвращается NIL.

VARLIST  

Функция VARLIST (реализованная только в 13-м ядре) отображает список активных в момент вызова переменных вместе с их типами. Функция принимает один необязательный параметр строкового типа. Если параметр задан, то в список переменых попадают только переменные, в имени которых присутствует заданная строка. Рассмотрим пример:


(setq *g* 100)

==> 100
Создана глобальная переменная *g*

(defvar *d* -100)

==> *d*

(defun f (x y) (varlist) (list x y))

==> f

(f 222 333)

+-------------------+---------+-----------+
| Имя переменной    | Тип     | Значение  |
+-------------------+---------+-----------+
|y                  |Лексич.  |333        |
|x                  |Лексич.  |222        |
|*d*                |Динамич. |-100       |
|*g*                |Глобальн.|100        |
+-------------------+---------+-----------+

==> (222 333)

(varlist)

+-------------------+---------+-----------+
| Имя переменной    | Тип     | Значение  |
+-------------------+---------+-----------+
|*d*                |Динамич. |-100       |
|*g*                |Глобальн.|100        |
+-------------------+---------+-----------+

==> T

Здесь создана глобальная переменная *g*, динамическая переменная *d*, после чего вызвана функция f, в теле которой содержится вызов VARLIST. Хорошо видно, что в точке вызова VARLIST активны четыре переменные - глобальная, динамическая и две лексические (параметры функции). Вызов функции VARLIST на верхнем уровне показывает, естественно, только две переменные - *g* и *d*.

Разумеется, увидеть переменные *g* и *d* можно при работе в IDE, нажав кнопку "Просмотр переменных", но лексические переменные можно увидеть только в отладчике.

WRITEIMAGE  

Функция WRITEIMAGE (реализованная только в 13-м ядре) сохраняет полный образ состояния Лисп-машины в двоичный файл на диске. В образ попадают все созданные объекты (включая графические окна с содержимым, диалоги, BLOB-ы, hash-таблицы). Функция принимает один необязательный параметр - имя файла-образа. Если параметр не задан, открывается стандартный диалог "Сохранить как". Если пользователь нажмет кнопку отказа, сохранение не выполняется. В качестве расширения файла-образа устанавливается .hli (HomeLisp Image).

Файл-образ, полученный в результате работы функции WRITEIMAGE, пригоден для последующей загрузки псевдо-функцией READIMAGE.

Важнейшее отличие функции WRITEIMAGE от функции WRS (описанной ниже) состоит в том, что функция WRS не способна сохранять циклические структуры. Это не представляется удивительным, поскольку функция WRS в сущности просто "печатает" все S-выражения в текстовый файл (а циклическая структура не может быть распечатана).

WRS  

Функция WRS обеспечивает выгрузку определяющих выражений всех функций, переменных и констант во внешний текстовый файл. Функция WRS имеет необязательный аргумент типа STRING, представляющий собой имя файла для выгрузки. Выгрузка осуществляется в файл с расширением lsp. Если задано другое расширение, то оно заменится на lsp. Если задано короткое имя файла, то он образуется в текущей директории.

Если аргумент Функции WRS опущен, то выводится стандартное диалоговое операционной системы "Cохранить как". В этом случае пользователь может отказаться от выгрузки, нажав кнопку "Отмена" или выполнить выгрузку, выбрав директорию и файл, и нажав кнопку "Сохранить".

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

При работе WEB-компоненты функция позволяет сохранить данные только в рабочую директорию авторизованного пользователя. Аргумент в этом случае является обязательным и не может содержать путь (диск и директорию).