2017-05-31 27 views
3

在朱莉娅,说我有一个变量的object_id但已经忘记了它的名字,我怎么可以检索使用ID的对象?我怎么能在朱莉娅的ID检索对象

I.e.我想要some_id = object_id(some_object)的倒数。

+2

'object_id'是散列函数,这通常意味着它不能容易地反转。另外,'some_object'可能不是一个变量,而是一个不可变的,它不会在后面存在。例如,'object_id(123)'返回一个值,但'123'不是一个变量,并且稍后在特定的内存位置不存在。想想解决问题的另一种方法可能会更好,可能使用Dict并将变量放入其中,并使用它们的'object_id(...)'作为键。 –

+2

有一个'ObjectIdDict',它可能用于'object_id'存储。但我认为这是相当无证的。 – phg

回答

6

由于@DanGetz在评论中说,object_id是散列函数,并设计为不是可逆的。 @phg也是正确的,ObjectIdDict正是用于这一目的(这是documented虽然没有在手册中讨论了):

ObjectIdDict([itr])

ObjectIdDict()构造一个哈希表,其中键是(总是) 对象身份。不像Dict它没有参数的关键和 值类型,因此它的eltype总是Pair{Any,Any}

进一步的帮助,请参见Dict

换句话说,它使用object_id作为散列函数散列对象===。如果你有一个ObjectIdDict,并且使用你遇到的对象作为它的键,那么你可以将它们保留在周围并在ObjectIdDict之外将它们恢复。

但是,这听起来像你想要做到这一点,没有明确的ObjectIdDict只是询问曾创建的对象有给定的object_id。如果是这样,请考虑这个想法实验:如果每个对象始终可以从其object_id中恢复,那么系统永远不会丢弃任何对象,因为程序通过ID来请求该对象总是可能的。所以你永远无法收集任何垃圾,并且每个程序的内存使用情况都会迅速扩展,以便使用所有的RAM和磁盘空间。这相当于有一个单一的全球ObjectIdDict,你把每一个对象创建到。因此,反过来,object_id函数不需要释放任何对象,这意味着你需要无限的内存。

即使我们有无限的记忆,还有更深层次的问题。对象存在意味着什么?在存在优化编译器的情况下,这个问题没有明确的答案。从程序员的角度来看,一个对象通常会被创建和操作,但实际上 - 从硬件的角度来看 - 它永远不会被创建。考虑一下这个功能,构建了一个复杂的号码,然后使用它进行一个简单的计算:

julia> function f(y::Real) 
      z = Complex(0,y) 
      w = 2z*im 
      return real(w) 
     end 
f (generic function with 1 method) 

julia> foo(123) 
-246 

从程序员的角度来看,这构建了复数z,然后构建2z,然后2z*im,最后构建real(2z*im)并返回该值。所以所有这些值都应该插入到“天空中的Great ObjectIdDict”中。但他们真的构建?下面是应用于Int此功能的LLVM代码:所有构造

julia> @code_llvm foo(123) 

define i64 @julia_foo_60833(i64) #0 !dbg !5 { 
top: 
    %1 = shl i64 %0, 1 
    %2 = sub i64 0, %1 
    ret i64 %2 
} 

没有Complex值!相反,所有的工作都是内联的,而不是实际完成的。整个计算归结为将参数加倍(通过将其左移一位)并将其反转(通过从零中减去它)。这种优化可以首先完成,因为中间步骤没有可观察到的副作用。编译器知道无法区分实际构造复杂值和对它们进行操作,只是做了几个整数运算 - 只要最终结果总是相同。隐在“天空之大ObjectIdDict”的想法是,似乎是实际制造的所有对象构造并插入到一个大的,永久性数据结构的假设 - 这是一个巨大的副作用。因此,不仅是从其ID中恢复对象与垃圾收集不兼容,它还与几乎所有可以想象的程序优化都不兼容。

除此之外,唯一一个可以设想反相object_id是计算上的需求,而不是因为它们是创建对象保存其反转的图像。这将解决内存和优化问题。当然,这是不可能的,因为有无限多的可能对象,但只有有限数量的对象ID。您是微乎其微不可能真正遇到两个对象在程序中相同的ID,但ID空间的有限性意味着反转散列函数原则是不可能因为每个ID值的原像包含潜在对象无限数量的。

我可能已经反驳了功能远远超过必要性的可能性,但它导致了一些有趣的思想实验,并且我希望这有助于 - 或者至少是令人兴奋的。实际的答案是,没有办法绕过明确存储每个对象,你可能想要回到ObjectIdDict