读取已定义函数的代码(尤其是从 System` 上下文)的最佳方法是什么?

发布于 2024-12-22 10:37:50 字数 943 浏览 5 评论 0原文

有时我们喜欢研究某些 System` 函数是如何定义的(当它们在 Mathematica 中编写时)。这个问题是关于做到这一点的最佳方法。

需要记住的要点:

  • 当然,需要首先删除 ReadProtected

  • 内置文件在加载到内核之前通常需要至少使用一次。当它们具有扩展功能(例如通过选项)时,单个简单调用通常足以满足此目的吗?

  • 信息 (??) 以难以阅读的格式给出定义(没有缩进,并且所有私有上下文名称都在前面)。摆脱上下文名称并获取格式化代码的最佳方法是什么?

    摆脱某些上下文的一个想法是Block[{$ContextPath = Append[$ContextPath, "SomeContext`Private`"], Information[symbol]]。可以使用 Workbench 自动格式化代码。仍然存在一些问题,例如 Information 没有引用字符串,导致代码无法复制到 Workbench 中。

一般来说,我感兴趣的是人们如何做到这一点,他们使用什么方法用于使内置代码尽可能易于阅读。

用例:例如,最近我深入研究了 RunThrough 的代码,发现它根本无法在 Windows XP 上工作(事实证明,当路径他们包含空格)。


更新: 看来曾经是一个用于打印没有上下文前缀的定义的函数,Developer`ContextFreeForm,但它在新版本中不再起作用。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

笔落惊风雨 2024-12-29 10:37:50

关于漂亮的打印:以下是一个非常示意性的代码,它建立在@Mr.Wizard的答案之上,以表明一些简单的规则可以对提高代码的可读性大有帮助:

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}], "]"}]
           }]]]]

这肯定不是一个通用的解决方案(特别是在没有许多单独语句的情况下,它不能在深度嵌套的函数代码上很好地工作),但我确信它可以得到改进和泛化,而不会遇到太多麻烦来覆盖许多感兴趣的情况。

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.

眉目亦如画i 2024-12-29 10:37:50

好问题,因为我认为我还没有看到这个问题的讨论。

我基本上做了你概述的同样的事情。您可以使用 Definition 获得稍有不同的打印输出,并使用 FullDefinition 获得更多信息:

Unprotect[RunThrough];

ClearAttributes[RunThrough, ReadProtected]

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

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
]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文