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

Wolfram mathematica 读取已定义函数的代码(尤其是从系统上下文)的最佳方法是什么?,wolfram-mathematica,reverse-engineering,Wolfram Mathematica,Reverse Engineering,有时我们喜欢研究某些系统`函数是如何定义的(当它们是用Mathematica编写时)。这个问题是关于最好的方法 要记住的要点: 需要首先删除的原因ReadProtected 内置程序通常需要在加载到内核之前至少使用一次。当它们具有扩展功能(例如,通过选项)时,单次简单调用通常就足够了吗 信息(??)以一种难以阅读的格式给出定义(无缩进,且所有私有上下文名称都在前面)。去除上下文名称并获取格式化代码的最佳方法是什么 摆脱某些上下文的一个想法是块[{$ContextPath=Append[$Con

有时我们喜欢研究某些
系统`
函数是如何定义的(当它们是用Mathematica编写时)。这个问题是关于最好的方法

要记住的要点:

  • 需要首先删除的原因
    ReadProtected

  • 内置程序通常需要在加载到内核之前至少使用一次。当它们具有扩展功能(例如,通过选项)时,单次简单调用通常就足够了吗

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

    摆脱某些上下文的一个想法是
    块[{$ContextPath=Append[$ContextPath,“SomeContext`Private`]”,信息[symbol]]
    。代码可以使用Workbench自动格式化。仍然存在一些问题,例如
    信息
    没有引用字符串,从而阻止代码被复制到Workbench中

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

用例:例如,最近我深入研究了
RunThrough
的代码,发现它在Windows XP上根本不起作用(当临时文件的路径包含空格时,它无法引用临时文件的名称)



更新:以前有一个函数,可以在没有上下文的情况下打印定义,
Developer`ContextFreeForm
,但是它在新版本中不再工作了。

问得好,因为我想我还没有看到讨论过这个问题

我做的基本上与您概述的相同。您可以使用
Definition
获得不同的打印输出,并使用
FullDefinition
获得更多信息:

Unprotect[RunThrough];

ClearAttributes[RunThrough, ReadProtected]

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

关于漂亮的打印:以下是一个基于@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}], "]"}]
           }]]]]

这肯定不是一个通用的解决方案(特别是如果没有许多单独的语句,它将无法在深度嵌套的函数代码上很好地工作),但我相信它可以改进和推广,而不需要太多麻烦来涵盖许多感兴趣的案例。

您可以通过在调用
+1之前输入上下文来摆脱私有上下文名称。我不知道您可以操纵上下文路径来实现相同的目标(关于去掉前置的私有上下文名称)。我总是使用BeginContext。我认为OPs问题的剩余部分的计算结果是“如何漂亮地打印Mathematica代码?”我所知道的唯一的源代码格式化程序是在Wolfram Workbench的编辑器上下文菜单中。@cah还有一个更重要的问题。尝试将
RunThrough
代码复制到Workbench,您会看到它会出现语法错误。这是因为字符串周围的引号没有打印出来,而这一个甚至包含两个纯空白字符串。所以下一件事是:如何以可粘贴的形式获取源代码?我在问题中提到的
$ContextPath
方法太小了。@cah
Begin
和朋友们所做的只是修改
$ContextPath
,仅此而已。@Mr Wizard我不确定您是否知道
不必取消保护
可以删除
ReadProtected
。我认为
Protected
不会影响属性的更改。@Szabolcs不,我没有意识到。我不认为复制粘贴有问题,但我也没有工作台。如果我复制到一个新的单元格,它看起来是正确的。在这个有限的示例中,这对于实际目的来说非常有效!@Mr.Wizard I找到了一个,很遗憾,他没有给出生成它的代码。@Szabolcs:很有趣。你试着联系作者了吗?@Mr.Wizard是的,到目前为止没有回复。但是现在是假期。@Szabolcs我忍不住注意到该页面上的快速排序函数没有得到很好的优化。我会写:
快速排序=#&@@@{#/.x:{y,{uu}:>(##&@@Reverse/@GatherBy[x,#
,它既短又快。@Mr.Wizard在那里写评论。