Отлаживаем макросы
Оглавление
Введение
Отладка макросов — дело более сложное, чем отладка обычного синтаксиса. В самом деле, мы не можем выполнять строки макросов одну за другой, как в обычном синтаксисе. Всё, что мы можем — вызвать макрос и посмотреть на результат. Первый шаг в отладке макросов — установка параметра SET MPRINT=yes /PRINTBACK=yes
. Это позволяет видеть синтаксис, генерируемый макросом, в окне вывода.
Другой полезный метод — сохранять файл данных в ключевых точках макроса с помощью команды SAVE OUTFILE
. Просматривая потом данные, сохранённые на разных этапах выполнения макроса, можно увидеть, где программа начинает работать «криво».
Компьютеры (по большей части) делают то, что вы им приказали делать, а не то, что вы хотите, чтобы они сделали :-)
На что обратить внимание
Опечатка в имени или пропуск параметра
Просто проверьте это еще раз, внимательно. Совет выглядит очень простым, но такие ошибки делают все, в том числе и я!
Параметр MXLOOPS
(сообщение разместил Mike Lacey в новостной группе SPSS 20.06.2000)
Только что осознал, что убил целый день из-за одной забавной особенности цикла LOOP
, в частности, параметра MXLOOPS
. Возможно, остальные пользователи хорошо осведомлены о MXLOOPS
, но я подозреваю, что нет.
MXLOOPS
устанавливает максимальное количество итераций в цикле LOOP
без индекса (т.е. в «бесконечном» цикле или цикле по условию IF
).
По умолчанию MXLOOPS
установлен в 40, но можно установить любое другое предельное число итераций командой SET MXLOOPS = n
.
Существование такой установки не сразу можно заметить, но вообще-то она означает, что цикл может прерваться ещё до выполнения условия IF
.
Смотрите, что происходит со следующим синтаксисом:
COMPUTE TRIALS = 100. COMPUTE #I = 1. LOOP. IF RV.UNIFORM(0,1) < 0.0001 X = 1. COMPUTE #I = #I + 1. END LOOP IF (#I > TRIALS) or (X = 1).
Подразумевается, что цикл должен выполняться на каждом наблюдении пока не будет сделано 100 попыток сгенерировать случайное значение, меньшее, чем 0.001 или пока переменная X не примет значение 2 в результате успешной генерации искомой величины. Однако, если MXLOOPS = 40
, очень часто цикл будет прекращаться до достижения любого из этих условий.
Гарантию выполнения одного из двух условий может дать установления практически бесконечного предела MXLOOPS
. Для смелых: SET MXLOOPS = 1E8.
Неверное применения !POS
-параметра
Допустим, вы задали макрос следующим образом:
DEFINE !mymacro (age=!TOKENS(1) /!POS=!CMDEND) … !ENDDEFINE.
и вызываете его таким образом:
!mymacro age=18 29 35 78.
Макрос не будет работать как надо, поскольку параметр age
не будет определён. Да, мы вызываем макрос с параметром age=18
, что, казалось бы, должно его определять. Но проблема в том, что значения «позиционного» параметра !POS
(на который можно ссылаться как на первый из заданных, второй из заданных и т.д.), по умолчанию идут перед всеми прочими параметрами. Более того, в данном случае значением этого параметра будет всё включительно до последней точки, т.е. в данном случае !POS =
«age=18 29 35 78». Парсер макросов просто не увидит параметра age
.
Странная особенность парсера макросов
Если в среди значений аргумента, передаваемых макросу при вызове, встречаются цифры и буквы, в частности:
- если за числами следуют буквы (например, 123ab), или
- за числом следуют буквы, а затем — снова числа (например, 123ab21), или
- за символом подчёркивания в начале следует число (например, _1)
то может проявиться странная особенность парсера макросов. См. этот файл с дальнейшими объяснениями.
...