clojure - 何时评估集合的唯一元素?

标签 clojure compilation

在什么时候评估集合的唯一元素。对于每个:

(def set1 #{1, 2, 3, 3})
(def set2 #{1, 2, 3, (+ 1 2)})

(defn foo 
[a b]
#{1, 2, a, b})

(foo 3 (+ 1 2))

它是编译时和运行时的组合还是其他什么?

最佳答案

我猜语法 #{...} 在读取时会转换为 (hash-set ...),并且所有内容都会被评估在运行时,就像任何正常的函数调用一样。在您的情况下,当您调用 foo 时,它首先评估 3,然后评估 (+ 1 2),然后调用 (foo 3 3) ,它又调用 (hash-set 1 2 3 3) 导致调用 (clojure.lang.PersistentHashSet/create keys),这增加了key 来一一设置。所以答案是:重复项在运行时被消除。

更新

正确答案是“两者”。

对于 op 的示例,它显然是在运行时执行的,这在 repl 中很容易看出:

user> (defn f [a b]
        (println "f" a b)
        #{1 2 a b})
#'user/f

user> (f 1 2)
f 1 2
IllegalArgumentException Duplicate key: 1  clojure.lang.PersistentHashSet.createWithCheck (PersistentHashSet.java:56)

so: f 编译正常,(f 1 2) 编译正常,执行时抛出异常。

正如 @Hoagy Carmichael 的回答中提到的,将相同的内容放入文件并使用 clojure 编译会引发错误,但这并不是因为编译器检查重复项,而是由于内部编译器在运行顶级表单后的行为汇编。所以这不是真正的编译时错误,而是运行时错误。而且,由于这是内部行为,我想没有人保证将来会是这样。

另一方面,当我粗略地简化了读者的行为时,我错了:它确实检查了传递给 #{} 表单的所有表单的“字面”唯一性。所有这些函数定义都无法编译:

user> (defn f1 [a b]
        #{1 1 a})
IllegalArgumentException Duplicate key: 1 

user> (defn f1 [a b]
        #{1 a a})
IllegalArgumentException Duplicate key: a  

user> (defn f1 [a b]
        #{1 (inc a) (inc a)})
IllegalArgumentException Duplicate key: (inc a)  

user> (defn f1 [a b]
        #{1 @a @a}) ;; notice that at run-time `@a` could easily produce different vals. But the reader sees equal forms.
IllegalArgumentException Duplicate key: (clojure.core/deref a)  

user> (defn f1 [a b]
        #{1 (+ a b) (+ a b)})
IllegalArgumentException Duplicate key: (+ a b)  

关于clojure - 何时评估集合的唯一元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39191323/

相关文章:

c - 创建/调用 DLL 时出现问题

Clojure 调用一系列函数并存储它们的返回值

clojure - 如何在 clojure repl 中使用 java.time? Java 互操作找不到类

class - 带类的Clojure案例陈述

clojure - 在clojure中生成从 'a'到 'z'的字符序列

java - 使用来自 Team Build Extensions 2010 的 ANT 构建 Java

maven - 将 Maven pom.xml 转换为 leiningen project.clj 的工具

performance - 如何提高 Golang 的编译速度?

c++ - 无法为Raspberry PI零w交叉编译Qt 5.14.2,因为它是 “requires a C++11 compiler”

python - 如何使用 gcc 从 Cython 编译 .c 代码