Clojure';s乐观主义者的工作,它在哪里?

Clojure';s乐观主义者的工作,它在哪里?,clojure,compiler-optimization,Clojure,Compiler Optimization,我不熟悉Clojure,但不熟悉lisp。一些设计决策对我来说很奇怪——特别是需要函数参数的向量,并使用recur显式地请求尾部调用 将列表转换为向量(反之亦然)是优化人员的标准操作。通过在编译为字节码之前重写为等效的clojure,可以将尾部调用转换为迭代。[]和recur语法表明当前实现中不存在这两种优化 我想要一个指针,指向我可以在中找到任何/所有源到源转换过程的位置。我的Java语言说得不太好,所以我很难在代码库中导航 如果在将函数逐个转换为JVM的字节码之前没有任何优化,我会对其设计原

我不熟悉Clojure,但不熟悉lisp。一些设计决策对我来说很奇怪——特别是需要函数参数的向量,并使用recur显式地请求尾部调用

将列表转换为向量(反之亦然)是优化人员的标准操作。通过在编译为字节码之前重写为等效的clojure,可以将尾部调用转换为迭代。[]和recur语法表明当前实现中不存在这两种优化

我想要一个指针,指向我可以在中找到任何/所有源到源转换过程的位置。我的Java语言说得不太好,所以我很难在代码库中导航

如果在将函数逐个转换为JVM的字节码之前没有任何优化,我会对其设计原理感兴趣。也许是为了实现更快的编译


谢谢。

编译器代码中没有明确的优化器包。任何优化都是“内联”完成的。有些可以通过编译器标志启用或禁用


请注意,函数参数的文字向量是一种语法选择,在源代码中如何表示函数。它们是否表示为向量、列表或其他任何形式都不会影响运行时,因此无法进行优化

关于自动重现,Rich Hickey解释了他的决定:

当谈到一般TCO时,我们不仅仅是在谈论 递归自调用,但也对其他函数进行尾部调用。总拥有成本 在后一种情况下,目前在JVM上是不可能的 保留Java调用约定(即不解释或 插入蹦床等)

虽然在跳跃中进行自尾呼叫很容易(毕竟, 这就是recur所做的),这样做会导致错误的结果 对来自具有完全TCO的计划(如Scheme)的人的期望。 因此,我们有一个显式的递归构造

从本质上讲,它可以归结为 优化和语义承诺。直到我能做出承诺, 我宁愿不要部分TCO

有些人甚至更喜欢“重复”而不是重复地重述 函数名。此外,recur可以强制尾部调用位置

特别需要函数参数的向量

大多数其他Lisp使用语法列表构建结构。例如,对于关联的“映射”,可以构建列表列表。对于“向量”,您可以列出一个列表。对于类似条件开关的表达式,可以创建列表列表。很多列表,很多括号

Clojure的一个明显目标是使lisp的语法更具可读性,减少冗余。map、set、list和vector都有自己的语法定界符,因此它们可以直接跳出来,同时还提供特定的功能,否则,如果它们都是列表,则必须使用函数显式请求这些功能。除了这些结构原语之外,其他函数,如
cond
通过为表达式中的每一对删除一层括号,而不是将每一对额外包装在另一个分组括号中,来最小化括号。这种理念在语言及其核心库中广泛存在,因此代码更具可读性和优雅性

函数参数作为向量只是该语法的一部分。这与语言是否能够轻松地将列表转换为向量无关,而是与语言如何要求在函数定义中放置函数参数有关——它通过显式要求向量来实现这一点。事实上,您可以在
defn
的源代码中清楚地看到这一点:


<>这只是一个函数如何编写的要求,就是这样。

什么让你认为Culjure向量是java向量或C++向量等等之类的东西?只是为了你没有看到它:@ MuHuk,我很确定Culjury的向量是用于关联数组的持久HAMT的专门化。我不相信我声称它们与std::vector有太多的共同点。(1)链接的特定行用于将单个函数声明包装到一个列表中,以始终具有
(fn name?([params*]exprs*)+)
函数定义。据我所知,这里没有转换。(2) 答案并没有真正解决这个问题,而且过于关注Clojure和Lisp语法。(3) 答案歪曲了lisp,说的是“香草lisp”,并声称只有列表:代码可以包含向量、字符串、数字、哈希表文本。@coredump-1)正确。Clojure没有发生转变,事实上我说的正好相反。2) 问题在于Clojure语言的设计决策,向量列表转换,以及它是否存在。3) 好的,我会改变措辞。我以前觉得它奇怪和烦人,但现在我更喜欢显式优化的重现。