【问题标题】:Why does Clojure's gensym increase by three on each call?为什么 Clojure 的 gensym 每次调用都会增加 3?
【发布时间】:2014-05-11 17:58:34
【问题描述】:

对 lisps 来说相当新,但在研究顺序整数生成代码时,我注意到重复调用 (gensym) 会将前缀后面提供的数字增加 3。我很好奇为什么会这样。

user=> (gensym)
G__662
user=> (gensym)
G__665
user=> (gensym)
G__668
user=> (gensym)
G__671
user=> (gensym)
G__674
user=> (gensym)
G__677

我已经看到并了解atominc 的组合使用,但我是gensym 函数的新手。

【问题讨论】:

  • 这样的问题让我想做一个 gensym 是 UUID 的 Lisp 实现。 ;-)
  • @ChrisJester-Young 现在我明白它们在语义上是 UUID,这是有道理的。

标签: clojure


【解决方案1】:

这里有很多正确答案。一个是:它没有!

user> (take 5 (repeatedly gensym))
(G__2173 G__2174 G__2175 G__2176 G__2177)

另一个是:gensym 不保证它生成的符号的形式,所以你真的不应该关心它们是否是连续的(或者即使它们根本包含数字)。你当然不应该劫持 gensym 来产生一个整数序列。

最后:为什么在您的示例中它增加了 3?因为每次评估 repl 中的表单时,编译器都必须创建自己的一些 gensym。显然,对于(gensym)这个表单,它需要创建的数字是两个。

【讨论】:

    【解决方案2】:

    没有!

    => (str (gensym) (gensym))
    "G__4027G__4028"
    

    查看 gensym 的来源我们可以看到它使用了 clojure.lang.RT/nextID。

    (defn gensym
      ([prefix-string] (. clojure.lang.Symbol (intern (str prefix-string (str (. clojure.lang.RT (nextID))))))))
    

    在 LispReader 中也使用了 nextID 函数。所以当你反复评估(gensym)时,读者很可能使用了两个ID。

    我的过程中显然还发生了其他事情,好像我在评估之间等待任何时间,消耗的 ID 更多,并且 gensym 差距超过 3 个。

    https://github.com/clojure/clojure/search?q=nextid

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-10
      • 2020-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多