问题:是否可以在不评估内容的情况下导入使用DumpSave
保存的MX文件?
让我说明一下:
让我们创建一个变量data
:
In[2]:= data = Range[10]
Out[2]= {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
可以将其导出到MX并从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文件保存为专门允许,否则无法执行此操作。
答案 0 :(得分:7)
我的理解是.mx文件的逻辑是反向的:当您加载.mx文件时,符号的定义(DownValues
和其他)在最低级别创建,因此值直接分配给内部存储器位置,绕过主评估器。这就是为什么加载.mx文件如此之快的原因。看来你不能同时拥有两者 - 你的期望与更高级别的符号代码相对应。但是,您可以通过在某些上下文中使用符号来封装数据,作为该数据的句柄。
所以,我在这里看不到真正的问题,因为你总是可以查询DownValues
和其他...Values
符号,并以未评估的形式提取规则的边缘(有一些DownValues
没有完全重建存储在其中的原始定义的病理情况,但它们可以说是零度量,而不是实际重要性)。您可以定义某个界面,这将允许您通过一些函数(符号)提取数据,而数据可以在封面下使用更多的符号,这些符号将隐藏在这些符号后面。
修改的
如果您控制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
来实际执行分配,但您也可以以未评估的形式访问它们。
答案 1 :(得分:2)
首先,我要指出DumpSave
似乎有一个未记录的第三个论证。我发现了这一点,同时拖着MX中的功能。
通过评估?System`Private`BuildApplicationMXFunction
来自己查看(修复这些上下文标记 - SO标记阻止使用常规符号)。请注意,在函数的最后一行,HoldAllComplete
作为第三个参数。
Dunno,如果这将是有用的。无论如何,这是我认为你要问的解决方案。
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
来评估和恢复原始作业{{1}}。
(现在是时候阅读列昂尼德的答案,看看我有多笨!! !! ):D