2012-01-04 3 views
7

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


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

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

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

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

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

In[3]:= [email protected][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 непосредственно управлять состоянием ядра вместо записи и чтение evaluatable определения как Save делает? Это просто догадка.


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


Ответ Оказывается, что это невозможно сделать, если файл MX не был сохранен в специально позволить.

ответ

7

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

Итак, здесь я не вижу реальной проблемы, так как вы всегда можете запросить DownValues и другие ...Values символов и извлечь r.h.(есть некоторые патологические случаи, для которых 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, чтобы на самом деле выполнить задания, но у вас также есть доступ к ним в неоцененной форме.

+0

@Szabolcs Я добавил код, чтобы проиллюстрировать ответ. –

2

Прежде всего, позвольте мне указать, что, как представляется, третий недопустимый аргумент для . Я обнаружил это при троллинге для функций с 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. Если вы используете версию Deferassignment, data снова будет неопределенным, и присвоение вернется (буквально) data = Range[10] Вы можете использовать [email protected]@assignment для оценки и восстановления исходного задания до data.

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

+0

Если вы вставляете встроенный код в двойные обратные выходы (\ '\'), тогда вы включаете в себя один обратный ход. См. Мое редактирование в ответ. – Szabolcs

+0

@Szabolcs Спасибо. Думал, я это пробовал.Иногда мгновенный просмотр кажется шелушащимся. Другой проблемой является интервал до и после встроенного кода. Если вы поместите пробел (как обычно, это делает), он будет набираться как два пробела. Не оставляйте места, и это выглядит так, как должно. Я использую несколько разных браузеров, но Chrome большую часть времени. – telefunkenvf14

Смежные вопросы