Setting up diagnostic error messages in large Mathematica projects

前端 未结 5 1895
春和景丽
春和景丽 2020-12-10 02:12

Whenever I create a large Mathematica project I run into this problem: Preventing avalanche of runtime errors in Mathematica, i.e., Mathematica\'s error message are opaque,

5条回答
  •  半阙折子戏
    2020-12-10 02:30

    A suggestion for extracting stack, maybe something that relies on Trace?

    An example of using Trace below, from Chris Chiasson. This code saves evaluation tree of 1 + Sin[x + y] + Tan[x + y] into ~/temp/msgStream.m

    Developer`ClearCache[];
    SetAttributes[recordSteps, HoldAll];
    recordSteps[expr_] :=
    
      Block[{$Output = List@OpenWrite["~/temp/msgStream.m"]}, 
       TracePrint[Unevaluated[expr], _?(FreeQ[#, Off] &), 
        TraceInternal -> True];
       Close /@ $Output;
       Thread[
        Union@Cases[
          ReadList["~/temp/msgStream.m", HoldComplete[Expression]], 
          symb_Symbol /; 
            AtomQ@Unevaluated@symb && 
             Context@Unevaluated@symb === "System`" :> 
           HoldComplete@symb, {0, Infinity}, Heads -> True], 
        HoldComplete]
       ];
    recordSteps[1 + Tan[x + y] + Sin[x + y]]
    

    To answer Samsdram's question, the code below (also from Chris) gives evaluation tree of a Mathematica expression. Here is the post from MathGroup with source code and examples.

    (Attributes@# = {HoldAllComplete}) & /@ {traceToTreeAux, toVertex, 
      HoldFormComplete, getAtoms, getAtomsAux}
    MakeBoxes[HoldFormComplete[args___], form_] := 
     MakeBoxes[HoldForm[args], form]
    edge[{head1_, pos1_, xpr1_}, {head2_, pos2_, xpr2_}] := 
     Quiet[Rule[{head1, vertexNumberFunction@pos1, xpr1}, {head2, 
        vertexNumberFunction@pos2, xpr2}], {Rule::"rhs"}]
    getAtomsAux[atom_ /; AtomQ@Unevaluated@atom] := 
     Sow[HoldFormComplete@atom, getAtomsAux]
    getAtomsAux[xpr_] := Map[getAtomsAux, Unevaluated@xpr, Heads -> True]
    getAtoms[xpr_] := Flatten@Reap[getAtomsAux@xpr][[2]]
    toVertex[traceToTreeAux[HoldForm[heldXpr_], pos_]] := toVertex[heldXpr]
    toVertex[traceToTreeAux[HoldForm[heldXprs___], pos_]] := 
     toVertex@traceToTreeAux[Sequence[], pos]
    (*this code is strong enough to not need the ToString commands,but \
    some of the resulting graph vertices give trouble to the graphing \
    routines*)
    toVertex[
      traceToTreeAux[xpr_, pos_]] := {ToString[
       Short@Extract[Unevaluated@xpr, 0, HoldFormComplete], StandardForm],
       pos, ToString[Short@First@originalTraceExtract@{pos}, StandardForm]}
    traceToTreeAux[xpr_ /; AtomQ@Unevaluated@xpr, ___] := Sequence[]
    traceToTreeAux[_HoldForm, ___] := Sequence[]
    traceToTreeAux[xpr_, pos_] := 
     With[{lhs = toVertex@traceToTreeAux[xpr, pos], 
       args = HoldComplete @@ Unevaluated@xpr}, 
      Identity[Sequence][
       ReleaseHold[
        Function[Null, edge[lhs, toVertex@#], HoldAllComplete] /@ args], 
       ReleaseHold@args]]
    traceToTree[xpr_] := 
     Block[{vertexNumber = -1, vertexNumberFunction, 
       originalTraceExtract}, 
      vertexNumberFunction[arg_] := 
       vertexNumberFunction[arg] = ++vertexNumber; 
      originalTraceExtract[pos_] := 
       Extract[Unevaluated@xpr, pos, HoldFormComplete]; {MapIndexed[
        traceToTreeAux, Unevaluated@xpr, {0, Infinity}]}]
    TraceTreeFormPlot[trace_, opts___] := 
      Block[{$traceExpressionToTree = True}, 
       Through@{Unprotect, Update}@SparseArray`ExpressionToTree; 
       SparseArray`ExpressionToTree[trace, Infinity] = traceToTree@trace; 
       With[{result = ToExpression@ToBoxes@TreeForm[trace, opts]}, 
        Through@{Unprotect, Update}@SparseArray`ExpressionToTree; 
        SparseArray`ExpressionToTree[trace, Infinity] =.; 
        Through@{Update, Protect, Update}@SparseArray`ExpressionToTree; 
        result]];
    
    TraceTreeFormPlot[Trace[Tan[x] + Sin[x] - 2*3 - 55]]
    

提交回复
热议问题