Как лучше всего прочитать код уже определенной функции (особенно из системного контекста)? - PullRequest
6 голосов
/ 22 декабря 2011

Иногда нам нравится смотреть, как определяются определенные функции System` (когда они написаны в Mathematica).Этот вопрос о том, как лучше всего это сделать.

Точки, которые следует иметь в виду:

  • Couse ReadProtected необходимо удалить в первую очередь.

  • Встроенные функции обычно необходимо использовать хотя бы один раз перед их загрузкой в ​​ядро.Достаточно ли одного простого вызова для этого, как правило, с расширенной функциональностью (например, с помощью опций)?

  • Information (??) дает определение, которое трудно прочитатьформат (без отступа, и все имена частных контекстов добавлены).Каков наилучший способ избавиться от имен контекста и получить отформатированный код?

    Одна из идей избавления от определенных контекстов - Block[{$ContextPath = Append[$ContextPath, "SomeContext`Private`"], Information[symbol]].Код может быть автоматически отформатирован с использованием Workbench.Некоторые проблемы остаются, например, Information не заключает в кавычки строки, препятствуя возможности копирования кода в Workbench.

В общем, мне интересно, как людисделайте это, какие методы они используют, чтобы сделать код встроенных программ настолько простым для чтения, насколько это возможно.

Вариант использования: например, недавно я копался в коде RunThrough, когда обнаружил, что он просто нене работает на Windows XP (оказывается, он не может процитировать имена временных файлов, когда путь к ним содержит пробелы).


Обновление: Появляется что раньше была функция для печати определений без добавления контекста, Developer`ContextFreeForm, но она больше не работает в более новых версиях.

Ответы [ 2 ]

7 голосов
/ 23 декабря 2011

Относительно симпатичной печати: ниже приведен очень схематичный код, основанный на ответе @ 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}], "]"}]
           }]]]]

Это, безусловно, не общее решение (в частности, оно не будет хорошо работать с глубоко вложенным функциональным кодом без множества отдельных операторов), но я уверен, что его можно улучшить и обобщить без особых проблем, чтобы охватить многиеинтересные случаи.

5 голосов
/ 22 декабря 2011

Хороший вопрос, потому что я не думаю, что это уже обсуждалось.

По сути, я делаю то же самое, что вы изложили.Вы можете получить несколько другую распечатку с помощью Definition, а дополнительную информацию - с помощью FullDefinition:

Unprotect[RunThrough];

ClearAttributes[RunThrough, ReadProtected]

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