14
$\begingroup$

I got this error when using Mathematica:

Part::partw: "Part 5 of {{0.637537,0.362463},{0.00038282,0.999617},
{0.0928437,0.907156},{0.0000222833,0.999978}} does not exist."

I know why it is generated, but the problem is my code is so lengthy and I cannot find where it comes from. Is there any syntax in Mathematica by which I can resolve my problem? Thanks.

$\endgroup$
  • $\begingroup$ Start by doing a search for [[5]]. $\endgroup$ – bbgodfrey Mar 24 '15 at 0:57
  • $\begingroup$ Try appending info to each message. $\endgroup$ – rcollyer Mar 24 '15 at 0:59
  • $\begingroup$ Break your code into cells and evaluate a few lines at a time. When they all work, consolidate them. $\endgroup$ – bill s Mar 24 '15 at 2:08
  • $\begingroup$ You could sprinkle a few Assert statements through your code testing whether the Part argument is longer than the list. $\endgroup$ – Sjoerd C. de Vries Mar 24 '15 at 6:41
  • $\begingroup$ Combine the function linked to by rcollyer with Stack and StackBegin. $\endgroup$ – Sjoerd C. de Vries Mar 24 '15 at 6:48
15
$\begingroup$

Implementation

Here is a better version of my debug function posted here, which would print the stack on the first message generated, and abort the computation. I have used it extensively with great effect in many cases.

This constructs the nested OpenerView from an arbitrary expression:

ClearAll[openerDress];
SetAttributes[openerDress, HoldAll];
openerDress[f_[args___]]:=
  OpenerView[{
    HoldForm[f],
    HoldForm[f]@@Map[openerDress,Unevaluated[{args}]]
  }];
openerDress[x_]:=HoldForm[x];

This uses openerDress to represent stack of execution in a way that is expandable when clicked:

ClearAll[stackPrettify];
stackPrettify[stack : {__HoldForm}] :=
  Column @ {
    Replace[stack, HoldForm[f_[x___]] :> openerDress[f[x]], 1],
    Style[Map[Short, Last[stack], {2}], Red]
  };
stackPrettify[___] := Null;

This is a generator of dynamic environments with redefined functions, encapsulating the Villegas - Gayley technique:

ClearAll[withRedefined];
withRedefined[f_Symbol, extraCondition_, beforeF_, afterF_]:=
  Function[
    code
    ,
    Internal`InheritedBlock[{f},
      Module[{inF, dv = DownValues[f]},
        Unprotect[f];
        DownValues[f]={};
        (call:f[args___]) /; extraCondition[args] && !TrueQ[inF]:=
          Block[{inF = True},
            beforeF[args];
            call;
            afterF[args]
          ];
        DownValues[f] = Join[DownValues[f],dv];
        Protect[f];
      ];
      code
    ]
    ,
    HoldAll
  ];

A couple more of the helper functions:

ClearAll[printStack];
printStack[start_, end_]:=Print[stackPrettify[Take[Stack[_], {start, end}]]];

ClearAll[heldF];
SetAttributes[heldF,  HoldAll];
heldF[body_]:=Function[Null, body, HoldAll];

Finally, this is the actual debugging utility (some formatting imperfections are due to the SE markdown bug regarding the display of symbols containing $):

ClearAll[debug];                        
debug[debugSymbol_Symbol:Message, failConditionFunction_:heldF[True]]:=
  Function[
    code
    ,
    Module[{tag},
      withRedefined[
        debugSymbol,
        heldF[!MatchQ[First[Hold[##]],_$Off]],
        heldF[If[failConditionFunction[##],printStack[6, -9]]],
        heldF[If[failConditionFunction[##], Throw[$Failed,tag]]]
      ][Catch[StackComplete[code],tag]]
    ]
    ,
    HoldAll
  ];

Tests

There are several ways one can use debug. The default one is that it breaks on first Message generated, and prints for you the stack. For example, one may try something like

debug[] @ Sin[Range[10][[1 ;; 15]]]

If you have an access to the source code which you want to debug, and can modify it, you could also use it in the following way:

ClearAll[$debugWrapper]
$debugWrapper[arg_] := arg;

and

debug[$debugWrapper][
  Sin[Part[Range[10], $debugWrapper[ 1 ;; 15]]]
]

In other words, you can wrap a piece of code where you suspect a problem, in some wrapper like $debugWrapper, and then extract the execution stack. You can also set a condition on the first event you want to trigger. For example, the following will only trigger the second event wrapped in $debugWrapper:

debug[
  $debugWrapper, 
  Function[arg, MatchQ[Unevaluated[arg], _Span], HoldAll]
][
   Sin[$debugWrapper@Part[Range[10], 1 ;; 15]];
   Sin[Part[Range[10], $debugWrapper[ 1 ;; 15]]]
]

in which case, only the second event wrapped in $debugWrapper, will be triggered.

$\endgroup$
13
$\begingroup$

Assuming your code is not too messy, you may have some luck with the built-in debugger. Go to Evaluation and check on Debugger. It will open a new panel, where you should have "Break at messages" checked.

enter image description here

After that, Mathematica will highlight the error for you with a green box:

enter image description here

$\endgroup$
  • 7
    $\begingroup$ Instead of relying on the green box, I like to use the "Show Stack" button. This doesn't require the code to be present in the notebook, and can show the values of variables. $\endgroup$ – Szabolcs Mar 24 '15 at 16:39
  • $\begingroup$ @Szabolcs Thanks for the tip! $\endgroup$ – egwene sedai Mar 24 '15 at 17:01
  • $\begingroup$ I use "Evaluate Cells" to run my code. Should I enable the "Debugger" and then "Break at Messages" before evaluating the cell or after that? $\endgroup$ – Alex Mar 24 '15 at 22:37
  • $\begingroup$ @Alireza Before evaluating. $\endgroup$ – egwene sedai Mar 25 '15 at 8:39
  • $\begingroup$ @egwene sedai Thank you very much! $\endgroup$ – Alex Mar 25 '15 at 16:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.