是否可以在不评估内容的情况下导入 MX 文件?

发布于 2024-12-25 00:56:47 字数 1337 浏览 2 评论 0原文

问题:是否可以导入使用 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 文件。


也许从技术上来说,避免定义是不可能的,因为 DumpSaveGet 直接操作内核状态,而不是像 Save 那样写入和读取可评估的定义。做?这只是一个猜测。


(编辑)请注意:我并不想以可以“保留”导入的方式保存。我已经可以使用 Export 来做到这一点。我希望导入以前的 DumpSaved MX 文件。


回答 看来不可能做到这一点,除非保存 MX 文件以明确允许它。

Question: Is it possible to import an MX file saved using DumpSave without evaluating the contents?


Let me illustrate:

Let's create a variable, data:

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

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

It can be exported to and imported from MX without making any definitions:

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

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

But what if we use DumpSave?

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

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

(And clear data)

In[5]:= Clear[data]

On re-import, nothing is returned:

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

But the variable data becomes defined again, as if we had used Get.

In[7]:= data

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

I would have expected to get something like Hold[data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}], i.e. something similar to what would be written to an .m file when using Save.


Perhaps it's technically impossible to avoid the definition being made because DumpSave and Get directly manipulate the kernel state instead of writing and reading an evaluatable definition like Save does? This is just a guess.


(edit) please note: I am not trying to save in a way that can be imported "Held". I can already do that using Export. I am looking to import previously DumpSaved MX files instead.


Answer It appears it is impossible to do this unless the MX file was saved to specifically allow it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

长亭外,古道边 2025-01-01 00:56:47

我的理解是,.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存储的code>。您只需对它们调用 ReleaseHold 即可实际执行分配,但您也可以以未评估的形式访问它们。

My understanding is that the logic of .mx files is the inverse one: when you load an .mx file, the definitions (DownValues and others) for symbols are created at the lowest level, so that the values are assigned directly to the internal memory locations, by-passing the main evaluator. This is the reason why loading .mx files is so fast. It seems that you can't have both - your expectation corresponds to a higher-level symbolic code. You can, however, encapsulate your data by using symbols in some context, as handles for that data.

So, I don't see a real problem here, since you can always query the DownValues and other ...Values of symbols and extract the r.h.sides of the rules in unevaluated form (there are some pathological cases for which DownValues don't fully reconstruct the original definitions being stored in them, but they are, so to say, of measure zero, and not much practical importance). You can define certain interface, which would allow you to extract your data via a few functions (symbols), while the data can use many more symbols under the cover, which would be hidden behind those.

EDIT

If you control the initial use of DumpSave, here is an illustration of one possibility - you can create a custom dumpSave-like function. These are helper function to prepare information on symbols:

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];

for example:

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]={}}]

Now, the main function:

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]
]

You basically designate a single symbol as a storage of unevaluated definitions of other symbols. Here is how you can use it:

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

If you now clear the storage symbol and load back the file, you will observe that all definitions of other saved symbols are stored in unevaluated form in DownValues of storage. You only need to call ReleaseHold on them to actually execute the assignments, but you also have access to them in unevaluated form.

红ご颜醉 2025-01-01 00:56:47

首先,让我指出,DumpSave 似乎有一个未记录的第三个参数。我在寻找带有 MX 的函数时发现了这一点。

通过评估 ?System`Private`BuildApplicationMXFunction 亲自查看(修复这些上下文标记 - SO 标记防止使用常规符号)。请注意,在函数的最后一行中,HoldAllComplete 作为第三个参数给出。

不知道这是否有用。无论如何,这是我认为您所问问题的解决方案。

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

根据您的需要,您也可以尝试赋值 := Defer[(data = Range[10])]

现在评估:

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

并注意,在评估赋值之前,data 是未定义的。如果您使用赋值Defer版本,data将再次未定义,并且赋值将返回(字面意思)data = Range[10 ] 您可以使用Evaluate@@assignment 来评估并恢复对data 的原始分配。

现在是时候阅读 Leonid 的答案,看看我有多蠢了!!):D

First, let me point out that there appears to be an undocumented third argument for DumpSave. I discovered this while trolling for functions with MX in them.

See for yourself by evaluating ?System`Private`BuildApplicationMXFunction (fix those context marks--SO markup prevents using the regular symbol). Note that in the last line of the function, HoldAllComplete is given as a third argument.

Dunno if that will be of use or not. Regardless, here's a solution to what I think you're asking.

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

Depending on what you want, you might also try assignment := Defer[(data = Range[10])].

Now evaluate:

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

And note that data is undefined until evaluating assignment. If you use the Defer version ofassignment,data will again be undefined and assignment will return (literally) data = Range[10] You could use Evaluate@@assignment to evaluate and restore the original assignment to data.

(Now it's time to read Leonid's answer and see how dumb I am!!) :D

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文