Генерация сообщений в математике

В модуле, который я пишу, у меня есть (для фаз разработки и тестирования) много Print["Messages"]. У меня есть два вопроса:

  • Какова наилучшая практика для печати таких сообщений "отладки"?
  • Есть ли способ вызвать модуль таким образом, чтобы сообщения НЕ были напечатаны? Например, при вызове модуля из другого модуля я бы хотел не видеть все выходные данные первого.

Ответ 1

Мне нравится всегда хранить глобальные переменные с префиксом $ и функции без префикса, поэтому я бы написал:

debugPrint[args___] := $debugPrintFunction[args]

$debugPrintFunction = Print[##] &

Тогда вы можете просто использовать debugPrint точно так же, как вы бы использовали Print сейчас. Когда вы хотите избавиться от отладочных сообщений, вы просто отключите переменную:

$debugPrintFunction = .

Есть несколько преимуществ для этого. Во-первых, вы можете использовать Block для локального включения и выключения отладки:

In[1]:= foo[x_] := (debugPrint[x]; x+1)

In[2]:= foo[3]
3
Out[2]= 4

In[3]:= Block[{$debugPrintFunction}, foo[3]
Out[3]= 4

Вы можете даже локально сделать $debugPrintFunction сделать что-то еще, например Sow значения для Reap, чтобы поднять или направить отладочные сообщения где-то еще, например

strm = OpenWrite["your/log/path/here", InputForm];
Block[{$debugPrintFunction = Write[strm, ##]},
  foo[3]];
Close[strm];

Используется разумно, динамическое масштабирование, предоставляемое Block, позволяет использовать глобальные переменные относительно безопасным и контролируемым образом.

Ответ 2

В моем старшем коде используется такой метод, как Pillsy.

В последнее время я использую голову, которая обычно не имеет никаких правил, например:

...
debugPrint[expr]
...

а затем вторую функцию:

Attributes[PrintDebug]={HoldAll}

PrintDebug[expr_] := Block[{debugPrint = Print}, expr]

Затем, когда я хочу увидеть вывод отладки, я могу обернуть PrintDebug вокруг ввода:

PrintDebug[MyFunction[1,2,3]]

или, чаще, как

MyFunction[1,2,3] // PrintDebug

так как я нашел постфиксную форму легче добавить/удалить и лучше оставить фокус на основной функции.

Ответ 3

Обычно я устанавливаю опцию verbosing в мои функции, которые могут быть включены/выключены, если необходимо для отладки. Обратите внимание, что, указав значение по умолчанию для Verbose внутри функции, вы можете контролировать, печатается ли информация или нет.

In[5]:= func1[arg_, opts___] := Module[{verbose},
   verbose = Verbose /. {opts} /. {Verbose -> True};
   If[verbose, Print["Verbosing function1: arg is ", arg]];
   arg
   ];

func2[arg_, opts___] := Module[{verbose},
   verbose = Verbose /. {opts} /. {Verbose -> False};
   func1[arg, Verbose -> verbose]
   ];

In[7]:= func1[123]

During evaluation of In[7]:= Verbosing function1: arg is 123

Out[7]= 123

In[8]:= func2[456]

Out[8]= 456

In[9]:= func1[123, Verbose -> False]

Out[9]= 123

In[10]:= func2[456, Verbose -> True]

During evaluation of In[10]:= Verbosing function1: arg is 456

Out[10]= 456

Конечно, этот пример можно привести в соответствие с стандартами программирования Mathematica (например, добавить заголовок Options[func1, Verbose -> ...], а затем получить доступ к опциям изнутри функции, но здесь дело не в этом.

Ответ 4

Еще одна возможность:

debugPrint::msg = "Debug message: `1`";    
debugPrint[msg_] := Message[debugPrint::msg, msg]

Используйте функцию следующим образом:

debugPrint["hello"]

Отключить или включить такие сообщения:

Off[debugPrint::msg]

On[debugPrint::msg]

Ответ 5

Для меня, поскольку у M нет встроенного отладчика, о котором я говорю, я трачу 50% своего времени только на отладку, которая могла быть сохранена, если был отладчик. 50% моего кода разработки - это операторы печати, так как без них я буду потерян, найдя, откуда исходит ошибка. (это тоже плохо, так как слишком много печатных сообщений в коде затрудняет просмотр алгоритма когда-то, он мешает, но не может его удалить, поскольку он может понадобиться позже).

Мне кажется удивительным, что такой мощный и гибкий вычислительный инструмент, как M, все еще имеет относительно менее развитую среду разработки. Когда я использую Matlab, мне нужно несколько секунд, чтобы найти ошибку, используя отладчик.

Кто-то может сказать, что Workbench для отладки. Я попытался использовать отладочную демонстрацию Manipulate, и я не могу понять это. Слишком сложно использовать. M нуждается в простой простой в использовании отладчик (в самом ноутбуке, а не в отдельной программе) и с номерами строк!

Хорошо, учитывая приведенное выше введение:), это то, что я сам делаю в ответ на ваш вопрос:

  • имеют разные уровни отладочных сообщений. грубый уровень и подробный уровень. Грубый уровень печатает только сообщение, когда оно входит в функцию и когда существует функция.

  • У меня есть кнопка в пользовательском интерфейсе для включения/выключения отладки (если вы используете программу на основе пользовательского интерфейса, иначе она будет в коде).

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

  • Каждое отладочное сообщение имеет имя функции, которое вызывало его при его запуске.

  • Если вы хотите контролировать отладку на уровне модуля, что я делаю, он просто создает локальный флаг отладки внутри модуля и каждый раз, когда я хочу отлаживать этот конкретный модуль, включаю его/выключать. Этот локальный флаг отладки принимает параметр глобального флага отладки. Таким образом, я могу отлаживать только один модуль, если хочу, а не остальную часть кода.

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

Вот полезная ссылка

http://reference.wolfram.com/mathematica/guide/TuningAndDebugging.html

отладчик workbench (если вы можете понять, как использовать debug Manipulate и Dynamics, сообщите мне)

http://www.wolfram.com/products/workbench/features/debug.html