Введение

Отладка макросов — дело более сложное, чем отладка обычного синтаксиса. В самом деле, мы не можем выполнять строки макросов одну за другой, как в обычном синтаксисе. Всё, что мы можем — вызвать макрос и посмотреть на результат. Первый шаг в отладке макросов — установка параметра 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)

то может проявиться странная особенность парсера макросов. См. этот файл с дальнейшими объяснениями.