Можно ли импортировать файл MX без оценки содержимого? - PullRequest
7 голосов
/ 04 января 2012

Вопрос: Можно ли импортировать файл MX, сохраненный с использованием DumpSave, без оценки содержимого?


Позвольте мне проиллюстрировать:

Давайте создадим переменную, data:

In[2]:= data = Range[10]

Out[2]= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

Она может быть экспортирована и импортирована из MX без каких-либо определений:

In[3]:= ImportString@ExportString[data, "MX"]

Out[3]= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

Но что если мы используемDumpSave?

In[4]:= DumpSave["data.mx", data]

Out[4]= {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}

(И очистить data)

In[5]:= Clear[data]

При повторном импорте ничего не возвращается:

In[6]:= Import["data.mx", {"MX", "HeldExpression"}]

Но переменнаяdata становится снова определенным, как если бы мы использовали Get.

In[7]:= data

Out[7]= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

Я бы ожидал получить что-то вроде Hold[data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}], то есть что-то похожее на то, что было бы записано в .mфайл при использовании Save.


Возможно, технически невозможно избежать определения, поскольку DumpSave и Get напрямую манипулируют состоянием ядра вместо записи и чтения оцениваемого определения, такого как Save делает?Это всего лишь предположение.


(редактировать), пожалуйста, обратите внимание: Я не пытаюсь сохранить таким способом, который можно импортировать "Задержано".Я уже могу сделать это, используя Export.Я пытаюсь импортировать ранее DumpSave d MX-файлы.


Ответ Похоже, что это невозможно сделать, если MX-файл не был сохранен, чтобы разрешить его.

Ответы [ 2 ]

7 голосов
/ 04 января 2012

Насколько я понимаю, логика файлов .mx обратная: когда вы загружаете файл .mx, определения (DownValues и другие) для символов создаются на самом низком уровне, так что значения присваиваются непосредственно в области внутренней памяти, минуя основной оценщик. Это причина, по которой загрузка .mx файлов происходит так быстро. Кажется, что вы не можете иметь оба - ваше ожидание соответствует высокоуровневому символическому коду. Однако вы можете инкапсулировать свои данные, используя символы в некотором контексте в качестве дескрипторов этих данных.

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

EDIT

Если вы контролируете первоначальное использование DumpSave, вот иллюстрация одной возможности - вы можете создать пользовательскую dumpSave -подобную функцию. Это вспомогательная функция для подготовки информации о символах:

ClearAll[dress];
dress[prop_] := 
   Function[s, With[{pr = prop[s]}, Hold[prop[s] = pr]], HoldAll]

ClearAll[getHeldProperties];
getHeldProperties[HoldComplete[s_Symbol]] :=
 Thread[
    Through[(dress /@ {
        DownValues, UpValues, OwnValues,
        SubValues, DefaultValues, NValues, 
        FormatValues, Options, Messages, 
        Attributes
      })[Unevaluated[s]]], 
    Hold];

например:

In[284]:= 
getHeldProperties[HoldComplete[data]]

Out[284]= Hold[{DownValues[data]={},UpValues[data]={},OwnValues[data]={HoldPattern[data]:>
{1,2,3,4,5,6,7,8,9,10}},SubValues[data]={},DefaultValues[data]={},
NValues[data]={},FormatValues[data]={},Options[data]={},Messages[data]={},
Attributes[data]={}}]

Теперь основная функция:

ClearAll[dumpSave];
SetAttributes[dumpSave, HoldRest];
dumpSave[file_String, storage_Symbol, symbs___] :=
  Module[{n = 1},
    Replace[
      Thread[HoldComplete[{symbs}]],
      held : HoldComplete[s_] :> 
         (storage[n++] = getHeldProperties[held]), 
      {1}];
    DumpSave[file, storage]
]

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

dumpSave["data.mx", storage, data, dumpSave, dress]

Если вы теперь очистите символ storage и загрузите файл обратно, вы заметите, что все определения других сохраненных символов сохраняются в неоцененной форме в DownValues из storage. Вам нужно только вызвать ReleaseHold для них, чтобы фактически выполнить назначения, но у вас также есть доступ к ним в неоцененной форме.

2 голосов
/ 05 января 2012

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

Убедитесь сами, оценив ?System`Private`BuildApplicationMXFunction (исправьте эти метки контекста - SO разметка не позволяет использовать обычный символ).Обратите внимание, что в последней строке функции в качестве третьего аргумента указывается HoldAllComplete.

Не знаю, будет ли это полезно или нет.В любом случае, вот решение того, о чем я думаю, вы спрашиваете.

Remove[data, assignment];
assignment := (data = Range[10])

В зависимости от того, что вы хотите, вы также можете попробовать assignment := Defer[(data = Range[10])].

Теперь оцените:

DumpSave["data.mx", assignment, HoldAllComplete] (*Also could try Unevaluated as 3rd arg *)
Remove[data, assignment];
Import["data.mx", "HeldExpression"]

И обратите внимание, что data не определено до оценки assignment.Если вы используете Defer версию assignment, data снова будет неопределенным, и назначение вернется (буквально) data = Range[10]. Вы можете использовать Evaluate@@assignment, чтобы оценить и восстановить исходное назначение в data.

( Теперь пришло время прочитать ответ Леонида и посмотреть, какой я тупой !! ): D

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...