Преобразование выражений с помощью FrontEnd
Как я недавно узнал, в Mathematica есть некоторые типы выражений, которые автоматически анализируются FrontEnd.
Например, если мы оцениваем HoldComplete[Rotate[Style[expr, Red], 0.5]]
мы видим, что FrontEnd не отображает оригинальное выражение:
Можно ли контролировать такое поведение FrontEnd?
И возможно ли получить полный список выражений, которые анализируются FrontEnd автоматически?
РЕДАКТИРОВАТЬ
Мы можем видеть звонки MakeBoxes
когда используешь Print
:
On[MakeBoxes]; Print[HoldComplete@Rotate["text", Pi/2]]
Но копирование-вставка напечатанного вывода дает измененное выражение: HoldComplete[Rotate["text", 1.5707963267948966]]
, Это показывает, что Print
не уважает HoldComplete
,
При создании вывода Cell
там должны быть призывы к MakeBoxes
тоже. Есть ли способ увидеть их?
4 ответа
Я нашел пост Джона Фульца с довольно четким объяснением того, как работает графическая функциональность:
В версии 6 ядро абсолютно не участвует в генерации визуализированного изображения. Шаги, предпринятые при отображении графики в версии 6, очень похожи на те, которые используются при отображении неграфического вывода. Это работает следующим образом:
1) Выражение оценивается и в конечном итоге производит что-то с головой
Graphics[]
или жеGraphics3D[]
,2) Полученное выражение передается через
MakeBoxes
,MakeBoxes
имеет набор правил, который превращает графическое выражение в язык ячеек, который интерфейс использует для представления графики. Например,In[9]:= MakeBoxes[Graphics[{Point[{0, 0}]}], StandardForm]
Out[9]= GraphicsBox[{PointBox[{0, 0}]}]
Внутренне, мы называем это "typeset" выражением. Может быть, немного странно думать о графике как о "набранной форме", но по сути это та же самая операция, которая происходит для набора текста (которая работала таким образом в течение 11 лет), поэтому я буду использовать этот термин.
3) Полученное выражение набора текста отправляется через интерфейс MathLink на внешний интерфейс.
4) Внешний интерфейс анализирует выражение typeset и создает внутренние объекты, которые обычно имеют взаимно однозначное соответствие выражению typeset.
5) Внешний интерфейс рендерит внутренние объекты.
Это означает, что преобразование выполняется в ядре путем вызова MakeBoxes
,
Этот вызов может быть перехвачен с помощью кода высокого уровня:
list = {};
MakeBoxes[expr_, form_] /; (AppendTo[list, HoldComplete[expr]];
True) := Null;
HoldComplete[Rotate[Style[expr, Red], 0.5]]
ClearAll[MakeBoxes];
list
Вот что мы получаем в качестве вывода:
Видно, что MakeBoxes
не уважает HoldAllComplete
приписывать.
Список символов, которые автоматически преобразуются перед отправкой в FrontEnd, из которого можно получить FormatValues
:
In[1]:= list =
Select[Names["*"],
ToExpression[#, InputForm,
Function[symbol, Length[FormatValues@symbol] > 0, HoldAll]] &];
list // Length
During evaluation of In[1]:= General::readp: Symbol I is read-protected. >>
Out[2]= 162
Есть два аспекта того, что вы видите. Во-первых, транскрипция выражения, которое вы ввели в блоки, и рендеринг этих блоков с помощью Front-End. По умолчанию выходные данные набираются с использованием StandardForm, у которого есть правило набора для визуализации графики и геометрических преобразований. Если вы используете InputForm, такого правила нет. Вы можете контролировать, какая форма используется через Настройки-> Оценка.
Вы можете убедиться, что HoldComplete правильно выполнил свою работу, используя InputForm или FullForm на входе или используя отображение InputForm на выходной ячейке.
РЕДАКТИРОВАТЬ, используя OutputForm:
В [13]: = OutputForm [%]
Out [13] // OutputForm = HoldComplete [Rotate [expr, 0.5]]
Что касается вашего вопроса о полном списке символов, он включает в себя графику, геометрические операции и, возможно, другие, но я не знаю, полный список.
Не совсем ответ, но в Предпочтения> Оценка есть варианты "Использовать только текстовые поля при преобразовании (ввод | вывод) в наборные формы".
Если вы проверите это, то с помощью Cell > Convert To... > StandardForm и т. Д.... будет показан Rotate[..] вместо визуально повернутого результата.
Джон Фульц недавно ответил на мой вопрос о конвертации TableForm
"набирать" выражения, и здесь стоит привести это, поскольку оно усиливает (хотя и частично противоречит) общее объяснение, приведенное в моем предыдущем ответе:
ToBoxes
возвращает именно то, что ядро отправляет внешнему интерфейсу без изменений (за исключением, в общем случае, семантики оценки и побочных эффектов, возможно, отличающихся, но это не проблема в вашем примере).Проблема в том, что у внешнего интерфейса есть две разные спецификации для определения
GridBox
параметры... один из которых относится к версии 3, а другой - к более обширному набору дат для версии 6. Интерфейс понимает оба набора параметров, но канонизирует все, что получает, до параметров версии 6.
GridBox
это единственная коробка, в которой было такое массовое изменение опций, и было необходимо поддерживать новую функциональность, которую мы добавили в v6. Но передний конец будет продолжать понимать старые опции в течение долгого времени (возможно, навсегда), поскольку старые опции появляются не только в некоторых конструкциях набора текста ядра, но и в старых файлах ноутбуков.
ToBoxes[]
изTableForm
создает устаревшие параметры, так как не было необходимости обновлять наборTableForm
через некоторое время (ToBoxes[]
изGrid
с другой стороны, использует современные опции). Преобразование выполняется внешним интерфейсом. Вы могли бы полагаться на интерфейс, чтобы сделать преобразование для вас, или вы могли бы выяснить, как параметры отображаются самостоятельно.
Таким образом, в этом случае последний этап преобразования выражения выполняется FrontEnd.