傳遞參數這個問題上通過的由M個參考對象(我的一個相關的問題是在這裏simple question on passing data between functions)使用結構參照
當我試圖找到一種方法,通過引用傳遞的東西沒有使用Unevaluted[]
或HoldFirst[]
,我誤以爲這種方法,儘管我不明白它是如何工作的以及使用它的任何隱藏風險,但它看起來對我來說確實很好。所以我想在這裏向專家展示它,並詢問他們是否認爲它可以安全地使用(我有非常大的演示,並需要將參數打包到許多不同結構中以幫助管理它們,這就是我如何找到它的原因方法,而我正在嘗試的東西)。
這裏的方法:首先,我們知道,一個人不能寫:要更新「P」在上面的是改變調用成爲
Remove[p]
foo[p_] := Module[{u},
u = Table[99, {10}];
p = u
];
p = 0;
foo[p];
一種方式
foo[[email protected]];
或者通過定義foo[]
與HoldFirst
。
但這裏是我發現的方式,它不通過引用傳遞,沒有任一:
我把所有的參數在結構(我現在做到這一點無論如何),並通過結構和然後一個可以更新結構的領域內foo[]
和更新將在從函數調用返回的途中反映:
Remove[parms]
foo[parms_] := Module[{u},
u = Table[99, {10}];
parms["p"] = u
];
parms["p"] = 0;
foo[parms];
現在,parms["p"]
包含在新的列表{99, 99, 99, 99, 99, 99, 99, 99, 99, 99}
小號o,parms
在foo[]
內被覆蓋/更新,我不必告訴M通過parms
作爲參考!
我在我的程序中試過這個,我沒有看到奇怪的副作用。 CDF已更新,沒有錯誤。我不知道這是如何工作的,可能是M將parms
中的所有字段視爲全局?
但無論是哪種情況,只要它提供了將我的許多參數打包到結構中的方法,我就很高興,同時我可以在結構中更新函數內部。
但我的問題是:你看到這個方法的一個主要問題?它如何在內部工作?我的意思是M如何在沒有我的情況下處理這個事情HoldFirst
或Unevaluated
?我知道我現在失去了像以前一樣進行參數檢查的能力,但是我不能擁有我想要的一切。正如我之前所說的,M需要一個真正的內置結構作爲語言的一部分並將其集成到其中。但是這是另一次談論。
順便說一句,迄今爲止我看到的最好的結構仿真是由Leonid Shifrin在本帖末尾貼出的這個結果here,但不幸的是我不能在演示中使用它,因爲它使用演示中不允許的符號CDF。
感謝
更新: 順便說一句,這下面是什麼,我認爲中號如何處理這個。這只是我的猜測:我認爲param
是某種查找表,它的字段只是用作索引(可能是一個哈希表?)然後param["p1"]
將包含地址(不是值)在param["p1"]
的實際值所在的堆的位置。
事情是這樣的:
所以,路過param
時,則函數foo[]
,打字param["p1"]=u
裏面的時候就會造成當前內存指向"p1"
被釋放出來,然後從堆中分配新內存,並在其中複製u
的值。
所以,回來後,這就是爲什麼我們看到param["p1"]
的內容發生了變化。但實際改變的是內存的內容是由param["p1"]
表示的地址指向的。 (有一個名稱,它是"p1"
,和地址字段,它指向該名稱"p1"
表示內容)
但是那麼這意味着,該地址本身,這"p1"
表示發生了變化,但查找名稱本身(即「p1」)沒有改變。
因此,由於名稱本身沒有改變,所以不需要使用HoldFirst,即使這個名稱所代表的數據被修改了嗎?
更新:
有這種方法的一個小故障,但它不是一個大問題,解決它:通過使用該索引對象方法的事情時,事實證明,缺一不可修改對象的一部分。例如,下面這不起作用:以上
foo[param_] := Module[{},
param["u"][[3]] = 99 (*trying to update PART of u *)
];
param["u"] = Table[0, {5}];
foo[param];
給出了錯誤
Set::setps: "param[u] in the part assignment is not a symbol"
但解決方法很簡單。做出一個要更新的一部分整場的本地副本,然後更新本地副本的(部分),然後寫拷貝回場,這樣
foo[param_] := Module[{u = param["u"]}, (* copy the whole field *)
u[[3]] = 99; (*update local copy *)
param["u"] = u (*now update the field, ok *)
];
param["u"] = Table[0, {5}];
foo[param];
嘛。如果可以更新部分領域,情況會更好,因此不需要「特殊」處理。但至少周圍的工作並沒有那麼糟糕。
更新 爲了完整起見,我想我提到了另一個有關使用索引對象和解決方法的細小問題。
我寫
param[u] = {1, 2, 3}
param[u][[1 ;; -1]]
預期它返回{1,2,3}
。
然後我發現我可以使用[email protected]
而不是param[u]
,這真的很有幫助,因爲太多固定的支架開始讓我頭疼。
但是當我輸入
[email protected][[1 ;; -1]]
期望像以前一樣得到相同的答案,事實並非如此。 (我想我知道爲什麼,運營商優先級問題,但那不是現在這一點),只是想說解決方法很簡單,可以使用param[u][[1 ;; -1]]
或使用([email protected])[[1 ;; -1]]
我喜歡([email protected])[[1 ;; -1]]
更多,所以這就是我現在用來訪問索引對象內的列表。
符號[email protected]
與我可以達到的標準記錄表示法是param.u
,因此我現在對索引對象感到高興,它似乎工作得很好。只需要注意幾件小事。
這個問題有很多。你有沒有具體的事情要做? – 2011-12-15 07:04:25