0
$\begingroup$
xxx[a_] := Module[{b},
   b = a + 2;
   b + 2];
xxx[2]

Is there a way to examine value of b was during last invocation? The underlying issue is that I refactored all of my utilities to use Module[{vars},...] to avoid conflicts, but sometimes the output doesn't make sense and I want to look at intermediates.

$\endgroup$
  • $\begingroup$ Sound like you want to know how to debug, am I correct? 2245 + linked topics. There is also 'debugging' section in mathematica.stackexchange.com/questions/18/… $\endgroup$ – Kuba Apr 27 '17 at 19:41
  • $\begingroup$ I just need the values, those internal variables should be accessible as something like that b$3848, right? $\endgroup$ – Yaroslav Bulatov Apr 27 '17 at 19:43
  • $\begingroup$ Depends, Module variables have an attribute Temporary and are cleared after execution if not needed anymore. $\endgroup$ – Kuba Apr 27 '17 at 19:44
  • $\begingroup$ I want to print value of b after the function finished. I'm guessing for this I need to disable garbage collection, and also find some way to find what the name of the variable was (is there some object that stores name of recently created vars like b$3848?) $\endgroup$ – Yaroslav Bulatov Apr 27 '17 at 20:13
  • $\begingroup$ Echo[b]? $\endgroup$ – rhermans Apr 27 '17 at 20:19
1
$\begingroup$

I think Trace/TracePrint might be what you are looking for. In:

xxx[a_] := Module[{b},
   b = a + 2;
   b + 2];
TracePrint[xxx[2], b]

Out:

b$508901 (* local variable name of b *)
4 (*b's value *)
6 (*xxx[2]'s result*)
$\endgroup$
0
$\begingroup$

While this is quite a hack (fair warning), you can use the following form to track your module values. Also a fair warning: I haven't tested this extensively, but it should work for simple examples at the least.

HackModules[code_] := Block[{Module},
  With[
    {results = Unique[]},
    SetAttributes[results, Temporary];
    results = {};
    Module[args_List, body_] := With[
      {syms = First@Replace[
         Hold[args],
         {HoldPattern[x_Symbol = y_] :> {HoldPattern[x], Hold[y]},
          HoldPattern[x_Symbol] :> HoldPattern[x]},
         {2}]},
      Do[
        SetAttributes[Evaluate@If[ListQ[s], s[[1, 1]], s[[1]]], Temporary],
        {s, syms}];
      With[
        {vars = Replace[
           Hold @@ List@Table[
             If[ListQ[s], Join[Hold[Evaluate@Unique[]], Last[s]], Unique[]],
             {s, syms}],
           Hold[a_, b_] :> Set[a, b],
           {2}]},
        With[
          {bodyResult = CompoundExpression @@ Join[
             First[Hold @@@ vars],
             ReplaceAll[
               Hold[body],
               MapThread[
                 If[ListQ[#1], First[#1], #1] -> #2 &,
                 {syms, vars[[1, All, 1]]}]]]},
          With[
            {finalVals = MapThread[
               If[ListQ[#1], First[#1], #1] -> #2 &,
               {syms, vars[[1, All, 1]]}]},
            AppendTo[results, Hold[body] :> finalVals];
            bodyResult]]]];
    SetAttributes[Module, HoldAll];
    With[
      {codeResult = code},
      {results, codeResult}]]];
SetAttributes[HackModules, HoldAll];

This basically watches every module call you make and yields a list of {moduleVariableValues, allCodeReturnValue}:

HackModules[
  Module[
    {y = Module[{x = 12},
       x -= 2;
       x + 4]},
    y *= 10;
    y - 40]]

{{Hold[x -= 2; (x + 4) y] :> {HoldPattern[x] -> 10, HoldPattern[y] -> 2},
Hold[z *= 10; z - 80] :> {HoldPattern[z] -> 280}},
200}

The first element of the returned list is a list of delayed-rules where the LHS is the held code (the bodies of the modules) and the RHS is a list of the module variables with their values at the end of the module evaluation.

$\endgroup$

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.