我正在寻找具有以下功能的数据结构或在 Clojure 中模拟它的方法(通过http://www.erlang.org/course/advanced.html#refs):
引用是具有两个属性的 erlang 对象:
它们可以由程序创建(使用 make_ref/0),并且可以比较它们是否相等。
Erlang 引用是唯一的,系统保证通过对 make_ref 的不同调用创建的两个引用永远不会匹配。保证不是 100% - 但与 >100% 相差很小:-)。
尤其是来自 Oz 语言的 Name 数据类型 (http://www.mozart-oz.org/documentation/tutorial/node3.html):
创建名称的唯一方法是调用过程 {NewName X},其中 X 被分配 >一个保证在全球范围内唯一的新名称。姓名不能伪造或印刷。
虽然“不可伪造”的值听起来很可疑,尤其是在像 Clojure 这样的动态语言中,这正是我要寻找的。Van Roy 在 CTM 中使用此功能来创建所谓的“安全数据结构”,然后在代码中用于在受信任实体之间共享的安全令牌:
declare NewWrapper in
proc {NewWrapper ?Wrap ?Unwrap}
Key={NewName}
in
fun {Wrap X}
fun {$ K} if K==Key then X end end
end
fun {Unwrap C}
{C Key}
end
end
% A secure declarative unbundled Stack
declare NewStack Push Pop IsEmpty in
local Wrap Unwrap in
{NewWrapper Wrap Unwrap}
fun {NewStack} {Wrap nil} end
fun {Push S E} {Wrap E|{Unwrap S}} end
fun {Pop S E}
case {Unwrap S} of X|S1 then E=X {Wrap S1} end
end
fun {IsEmpty S} {Unwrap S}==nil end
end
可以在 Clojure 中模拟这种行为吗?这样我可以保证,例如,当且仅当我授予他令牌时,程序员才能解开数据结构。我知道它可能是不安全的,但我想找到在功能上与 Van Roy 相同的解决方案,并且至少很难被程序员规避。
下一个要求是基于纯 Clojure 而不是 JVM 魔术 - 所以没有“token = new Object()”等。例如,函数值看起来像一个很好的候选者,因为 AFAIK after (defn f [] nil) then (identical ? fx) 仅在 x=f 时计算为真,并且 f 不像函数式语言中的其他构造那样受到内存优化的影响(或者是吗?)。但是,这种方法可能会产生我不知道的进一步后果。上面示例中的 {NewName} 是否可以只替换为新的匿名函数(提供非分布式环境)?