2017-05-31 26 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