Debugging tips: nothing


Revision as of 19:14, 28 April 2016 by Thomas Linder Puls (talk | contribs) (category)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

This article contains a few debug tips. For all of them the solution is/involves core::nothing.

Caveat: The tips all involves recompiling the program, so they may not be applied to all kind of customer scenarios.

core::nothing is a predicate that takes any arguments and does nothing</vp>.

    nothing : (...) [deprecated("Should not be used in production code")]. % Not really deprecated
    % @short This predicate does nothing, but is useful in debug context.
    % For example to make sure that the variables are visible in the variables window.
    % @end

It is declared as deprecated so that usage issues a deprecated warning, which reminds you about removing it again, when it has served its debugging purpose.

Last call optimization

Due to last call optimization entries may be missing in the run stack window (and therefore the local variables are lost). It looks as if ppp called rrr, but actualy ppp called qqq which then called rrr; the qqq entry and the local variables there are not present at that debug time.

    ppp() :-
        qqq(). % "last call" disappears in the run stack and variables window
    qqq() :-

When placing nothing last in a clause it is the one that receives last call optimizations, so the "old" last call is no longer optimized:

    ppp() :-
        qqq(), % no longer last call, will appear in run stack

Non visible variable values

Due to other optimizations (this problem may become worse in the future, who knows) the values of variables may be "lost" at points where you would think they should still exist.

A typical example are semi-anonymous variables (e.g. _X) which often don’t show up in the variables window.

    rrr() :-
        get_some_things(_X, Y),
        qqq(Y).  % _X is not shown in the variables window

By passing variables as argument to nothing, you can keep/make them alive, so that they can be seen in the variables window:

    rrr() :-
        get_some_things(X, Y),
        core::nothing(X).  % keep X alive/visible even though we don't really need it

Conditional break points

People often suggest that breakpoints should be conditional. Actually they are, but only very few knows the language, in which you write the conditions.

    rrr(X) :-
        qqq(X). % only break when X is "Special"

There is however one language you know, and in which you can write the appropriate condition: Visual Prolog.

    rrr(X) :-
        if "Special" = X then
            core::nothing() % "conditional" break point here, i.e. only break when X is "Special"
        end if,

I used to write succeed instead of nothing. It is just as good for breaking, but unfortunately it has a tendency to stay in the code, when it goes into production. nothing is deprecated, so there is a much larger chance that it is found in due time.