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:
Of couse ReadProtected
needs to be removed first.
Builtins usually need to be used at least once before they get loaded into the kernel. Is a single simple invocation usually sufficient for this when they have extended functionality (e.g. through options)?
Information
(??
) gives the definition in a hard-to-read format (no indentation, and all private context names prepended). What is the best way to get rid of the context names, and get formatted code?
One idea for getting rid of certain contexts is Block[{$ContextPath = Append[$ContextPath, "SomeContext`Private`"], Information[symbol]]
. Code can be auto-formatted using Workbench. Some issues remain, e.g. Information
doesn't quote strings, preventing the code from being able to be copied into Workbench.
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.
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.
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
]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With