Szabolcs
Szabolcs

Reputation: 25703

What is the best way to read the code of already defined function (especially from the System` context)?

Occasionally we like to look into how certain System` functions are defined (when they're written in Mathematica). This question is about the best way to do that.

Points to keep in mind:

Generally, I'm interested in how people do this, what methods they use to make the code of builtins as easy to read as possible.

Use case: For example, recently I digged into the code of RunThrough when I found out that it simply doesn't work on Windows XP (turns out it fails to quote the names of temp files when the path to them contains spaces).


Update: It appears that there used to be a function for printing definitions without context prepended, Developer`ContextFreeForm, but it's not working any more in newer versions.

Upvotes: 8

Views: 825

Answers (2)

Leonid Shifrin
Leonid Shifrin

Reputation: 22579

Regarding the pretty-printing: the following is a very schematic code which builds on the answer of @Mr.Wizard to show that a few simple rules can go a long way towards improving the readability of the code:

Internal`InheritedBlock[{RunThrough},
   Unprotect[RunThrough];
   ClearAttributes[RunThrough, ReadProtected];
   Block[{$ContextPath = Append[$ContextPath, "System`Dump`"]},
      With[{boxes = ToBoxes@ DownValues[RunThrough]},
         CellPrint[Cell[BoxData[#], "Input"]] &[
            boxes /. 
            f_[left___, "\[RuleDelayed]", right___] :> 
                 f[left, "\[RuleDelayed]", "\n", right] //.
           {
             RowBox[{left___, ";", next : Except["\n"], right___}] :> 
                 RowBox[{left, ";", "\n", "\t", next, right}],
             RowBox[{sc : ("Block" | "Module" | "With"), "[", 
               RowBox[{vars_, ",", body_}], "]"}] :>
                 RowBox[{sc, "[", RowBox[{vars, ",", "\n\t", body}], "]"}]
           }]]]]

This is for sure not a general solution (in particular it won't work well on deeply nested functional code without many separate statements), but I am sure it can be improved and generalized without too much trouble to cover many cases of interest.

Upvotes: 9

Mr.Wizard
Mr.Wizard

Reputation: 24336

Good question, because I don't think I have seen this discussed yet.

I do essentially the same thing you outlined. You can get a somewhat different print-out with Definition, and more information with FullDefinition:

Unprotect[RunThrough];

ClearAttributes[RunThrough, ReadProtected]

Block[{$ContextPath = Append[$ContextPath, "System`Dump`"]}, 
  Print @ FullDefinition @ RunThrough
]

Upvotes: 5

Related Questions