为什么 Clojure 变量 arity args 根据使用而获得不同的类型?

2024-01-03

在回答中另一个问题 https://stackoverflow.com/questions/26039461/does-clojure-have-the-c-sharp-equivalent-of-yield/26040454#comment40792827_26040416我在 Clojure 的变量 arity 函数 args 中发现了一些我没有想到的东西:

user=> (defn wtf [& more] (println (type more)) :ok)
#'user/wtf

;; 1)
user=> (wtf 1 2 3 4)
clojure.lang.ArraySeq
:ok

;; 2)
user=> (let [x (wtf 1 2 3 4)] x)
clojure.lang.ArraySeq
:ok

;; 3)
user=> (def x (wtf 1 2 3 4))
clojure.lang.PersistentVector$ChunkedSeq
#'user/x
user=> x
:ok

为什么是类型ArraySeq在 1) 和 2) 中,但是PersistentVector$ChunkedSeq in 3)?


简短回答:这是 Clojure 的一个晦涩的实现细节。该语言唯一保证的是可变参数函数的剩余参数将作为clojure.lang.ISeq, or nil如果没有其他参数。您应该相应地编码。

长答案:它与函数调用是编译还是简单评估有关。无需深入探讨求值和编译之间的差异,了解 Clojure 代码被解析为 AST 就足够了。根据上下文,AST 中的表达式可以直接求值(类似于解释),也可以编译为 Java 字节码,作为动态生成的类的一部分。后者发生的典型情况是在 lambda 表达式的主体中,该表达式将计算为动态生成的类的实例,该类实现了IFn界面。请参阅Clojure 文档 http://clojure.org/evaluation以获得更详细的评估解释。

绝大多数时候,编译代码和评估代码之间的差异对于您的程序来说是不可见的;他们的行为方式完全相同。这是罕见的极端情况之一,编译和评估会导致行为略有不同。不过,需要指出的是,这两种行为都是正确的,因为它们符合语言做出的承诺。

Clojure 代码中的函数调用被解析为一个实例InvokeExpr in clojure.lang.Compiler。如果正在编译代码,则编译器会发出字节码,该字节码将调用invoke上的方法IFn使用适当的数量的对象(Compiler.java,第 3650 行 https://github.com/clojure/clojure/blob/clojure-1.6.0/src/jvm/clojure/lang/Compiler.java#L3650)。如果代码只是被评估而不是被编译,那么函数参数将被捆绑在一个PersistentVector并传递给applyTo方法上的IFn目的 (Compiler.java,第 3553 行 https://github.com/clojure/clojure/blob/clojure-1.6.0/src/jvm/clojure/lang/Compiler.java#L3553).

具有可变参数列表的 Clojure 函数被编译成clojure.lang.RestFn https://github.com/clojure/clojure/blob/clojure-1.6.0/src/jvm/clojure/lang/RestFn.java班级。这个类实现了所有的方法IFn,收集参数,并分派到适当的doInvoke数量。你可以在执行中看到applyTo也就是说,在 0 个必需参数的情况下(就像你的情况一样)wtf函数),输入 seq 被传递到doInvoke方法并对函数实现可见。 4-arg 版本invoke同时,将参数捆绑在一个ArraySeq并将其传递给doInvoke方法,所以现在你的代码看到一个ArraySeq.

让事情变得复杂的是,Clojure 的实现eval函数(这是 REPL 所调用的)将在内部包装一个在 thunk(一个匿名的无参数函数)内评估的列表形式,然后编译并执行该 thunk。因此几乎所有调用都使用对invoke方法,而不是由编译器直接解释。有一个特殊情况def显式评估代码而不进行编译的表单,这解释了您在那里看到的不同行为。

实施clojure.core/apply也称为applyTo方法,并通过此逻辑传递给任何列表类型apply应该看到函数体。的确:

user=> (apply wtf [1 2 3 4])
clojure.lang.PersistentVector$ChunkedSeq
:ok

user=> (apply wtf (list 1 2 3 4))
clojure.lang.PersistentList
:ok
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 Clojure 变量 arity args 根据使用而获得不同的类型? 的相关文章

  • 转发 UIAlertView 的可变参数

    我正在尝试设置一个非常简单的UIAlertView带有文本编辑 确定和取消按钮 我想根据文本编辑的内容禁用确定按钮 为了能够保留委托 以便他不会在警报视图之前消失 从而在用户对警报视图执行某些操作时立即导致崩溃 我对其进行了子类化 现在 我
  • lxml 的类型提示?

    Python 新手 具有静态类型语言背景 我想要类型提示https lxml de https lxml de只是为了便于开发 mypy 标记问题并建议方法会很好 据我所知 这是一个 python 2 0 模块 没有类型 目前我用过http
  • Clojure 的映射和减少 Monad...Juxt Monad 怎么样?

    在学习 Clojure 的过程中 我花了很长时间试图理解 monad 它们是什么以及我们如何使用它们 但没有取得太大成功 然而 我发现了一个很棒的 Monads for Dummies 视频系列 http vimeo com 2071730
  • 为什么这个 Clojure 程序在可变数组上运行如此慢?

    剧透警告 这是 代码降临 第六天的第一部分 我试图解决this http adventofcode com day 6Clojure 和 Scala 中的问题 Scala 程序在我的 Macbook Air 上运行良好 几秒钟内就完成了 然
  • 使用 swank-clojure 攻击 Clojure 库的工作流程

    Clojure 库的黑客攻击有典型的工作流程吗 假设我的应用程序 Foo 依赖于第三方库 Bar 该库是从存储库获取的 并通过以下方式包含在项目 Foo 中lein deps 然后 假设我想破解 Bar 库 所以我从 github 克隆它
  • Clojure 的分析工具?

    有谁知道 Clojure 有一个好的分析工具或库吗 我更喜欢可以从 REPL 中使用的东西 类似于 with profiling 过去是在 Allegro Common Lisp 中 有什么类似的事情吗 或者您是否有过与 Clojure 配
  • Oracle中“NUMBER”和“NUMBER(*,0)”相同吗?

    在甲骨文中文档 http docs oracle com cd B28359 01 server 111 b28318 datatype htm i22289据说 数字 精度 小数位数 如果未指定精度 则该列将存储给定的值 如果 未指定比例
  • clojure - 不同命名空间中的评估代码

    我正在编写类似 REPL Server 的代码 用户的请求在这样的函数中评估 defn execute request str try eval read string request catch Exception e getLocali
  • 在 Android 上运行 Java 字节码 - DalvikVM 之上的 Sun JVM

    由于 java 实现 OpenJDK 和Android的虚拟机DalvikVM是开源的 因此必须可以在Google的DalvikVM之上实现Sun的JavaVM 这将使运行基于 JVM 的应用程序和语言成为可能 Clojure Jython
  • SSIS Excel 导入强制错误的列类型

    我正在尝试使用 SSIS 将电子表格导入到我们的数据库中 由于某种原因 当其中两列包含字符数据时 SSIS 希望相信它们的类型为 Double 我尝试将列重新映射为 nvarchar 255 但它仍然不想选择它认为是双精度的数据 因为其中有
  • 在 Clojure 中的函数上使用“apply”时,如何显式指定名称空间?

    这里的 graph 是高阶函数 它返回一个在其范围内设置了配置的函数 ns bulbs neo4jserver graph defn out1 Test func that simply returns out1 config out1 d
  • 惰性序列内部究竟如何工作

    我是 clojure 的新手 不清楚惰性序列在内部是如何工作的 或者更具体地说 返回惰性序列的函数意味着只有在需要时才会计算结果 例如在下面的例子中 defn fc lazy fn xs lazy seq if let xss seq xs
  • 类型转换为具有相同属性的另一个

    在我的应用程序的一个部分中 我使用从 xsd 方案生成的类型 我有 2 个版本的架构 2008 和 2009 我使用的类型是 DatumType 在每个方案中 该类型都包含相同的属性 它们是精确的 除了命名空间 有什么方法可以将 Datum
  • 如何禁用 Clojure 断言,包括前提条件?

    在 REPL 中禁用 Clojure 断言 包括前置条件和后置条件 有哪些好方法 对于任意的莱宁根轮廓 Per https github com technomancy leiningen blob b82b228 sample proje
  • 如何定义与更高类型类型(类型构造函数)绑定的上下文

    我尝试过以下方法 def test Option T Ordering value1 Option T value2 Option T val e implicitly Ordering Option T compare value1 va
  • 您可以为 None 指定类型参数或告诉编译器它是一个 Option[String] 吗?

    我想知道我是否可以在我的代码中写这样的东西 None String 我很惊讶没有人提到它的存在Option empty scala gt Option empty String res0 Option String None 请注意 在许多
  • 到底什么是单例类型?

    什么是单例类型 有什么应用和影响 我们非常欢迎示例 更欢迎外行术语 如果将类型视为一组值 则值的单例类型x是仅包含该值的类型 x 用法示例 模式匹配 case Foo type检查匹配的对象是否与Foo using eq where cas
  • Java中有默认的数字类型吗

    如果我写这样的东西 System out println 18 哪种类型有 18 是吗int or byte 或者它还没有类型 它不能是 int 因为这样的东西是正确的 byte b 3 这是不正确的 int i 3 byte bb i e
  • Python 检查整数输入

    我试图允许用户输入我的程序 但是当他们输入字符串时我的程序失败 这是一个更大的程序 但正在尝试纠正问题 到目前为止我已经 data raw input Enter a number number eval data if type numb
  • 用纯函数式语言保持状态

    我正在尝试弄清楚如何执行以下操作 假设您正在开发直流电机的控制器 您希望让它以用户设置的特定速度旋转 def set point ref sp 90 while true let curr read speed controller set

随机推荐

  • 更改现有数据框的架构

    我想更改现有数据框的架构 在更改架构时遇到错误 我是否可以更改数据框的现有架构 val customSchema StructType Array StructField data typ StringType nullable false
  • 在 g++ 4.4.3 上得到负 NaN,这是标准吗?

    我在带有 Ubuntu Lucid Lynx 的 Linux 上安装了 g 4 4 3 并且得到了 nan 因此 在带有 g 4 3 1 的 Hardy Heron 上 我得到了所有 nan 这导致我的文本差异回归失败 因为我使用 cout
  • Solr、Sunspot、SQlite 和 Rails

    我想为我的使用 SQlite3 作为数据库的项目实现全文搜索 分面 听说Solr真的很强大 有 Sunspot 和 Solr 教程可用 但仅适用于 MySQL 我找不到任何有关如何为 SQLite3 设置它的文档 有人知道如何使用 SQLi
  • 使用数据表运行 100,000 次 Fisher 精确检验比应用慢

    早上好 我正在尝试使用 R 非常快速地对模拟遗传数据运行 100 000 次 Fisher 精确测试 最好在 30 秒内完成 因为我需要排列病例对照标签并迭代该过程 1 000 次 因此它会运行一夜 我尝试使用融化 整齐的数据上的数据表 其
  • 一个项目可以有多个起源吗?

    一个项目在 Git 中可以有两个 或多个 起源 吗 我想将一个项目推向两者github https github com and a Heroku https www heroku com server 具体来说 添加github仓库时出现
  • beginReceivingRemoteControlEvents 不触发 Apple Music 事件

    我正在从我的应用程序播放 Apple Music Apple Music 播放器代码如下 void submitAppleMusicTrackWithProductID NSString productID productID in US
  • 这个语法在 Javascript 中的含义是什么

    我正在 javascript 中寻找 TWILIO 的 API 我发现了类似的东西 const connect createLocalTracks Twilio Video navigator mediaDevices enumerateD
  • 没有异常处理的力量?

    在 Eclipse 中进行 Java 编程 我习惯于处理异常 在使用 VisualStudio 的 C 中 似乎我不能在方法上说 抛出异常 经过大量编码后 我发现了很多异常 并且必须在测试过程中发现它们时捕获它们 我想被迫处理它们 以便 V
  • 如何对 foreach 循环中迭代的元素进行分段

    我需要循环遍历整个用户列表 但需要一次获取 20 个 foreach var student in Class Students Take 20 Console WriteLine You belong to Group groupNumb
  • 无法自动装配方法

    我收到这个错误 org springframework beans factory BeanCreationException Could not autowire method 这是我的spring的xml配置
  • UIPickerView Swift 上奇怪的自定义背景颜色

    将自定义 UIColor 分配给 UIPickerViews 的背景时 我得到了奇怪的颜色 我为 textViews 和 pickerViews 创建了颜色 如下所示 let myTextViewBackgroundColor UIColo
  • 当node.js宕机时,如何让它自动恢复?

    由于节点基本上是一个进程 因此当出现严重错误时 整个应用程序就会崩溃 我现在有几个基于 Express 构建的应用程序 并且我正在使用一些手动方法来防止延长停机时间 process on uncaughtException 和自定义心跳监视
  • Mysql find_in_set 斜杠( / ) 分隔符

    我的值为 1 2 3 4 5 2 3 6 我想找到值 2 所以结果必须是 1 2 2 3 6 我不想使用 LIKE 运算符 有没有办法在FIND IN SET函数中设置分隔符 您可以使用like or find in set 这是一种方法
  • 如何编写 javascript 来重新排序 pdf 文档的页面?

    我有一个双面文档作为两个单独的 pdf 文件 一个文档的正面页面和第二个文档的背面页面 front pdf rear pdf 我还将它们合并为一个包含所有页面的文档 但所有正面页面都在背面页面之前 页面排序的形式为 1 3 5 7 n 2
  • Spring 启动和 SQLite

    我正在尝试将 SQLite 与 Spring Boot 应用程序一起使用 我知道 Spring Boot 对 MongoDB 等提供了出色的支持 但我找不到将 Spring Boot 与 SQLite 结合使用的方法 有什么建议从哪里或如何
  • android中的sqlite示例程序[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我是数据库概念的新手 特别是我需要相关的数据库概念 我想要一个在 android 上使用 sqlite 数据库的示例 我浏览了 andro
  • 替换php数组中的所有键

    这是我的数组 apple some code beta other code cat other code 2 如何将所有 e 字母替换为 在键名称中并保留值 这样我就会得到类似的东西 appl some code b ta other c
  • 当我尝试添加文本剪辑时,出现有关 ImageMagick With Python/MoviePy 的错误

    我正在使用 python 3 8 5 以及最新版本的 imagemagick 和 moviepy 错误 与代码 Traceback most recent call last File C Users edgib102 AppData Lo
  • JVM 内存使用失控

    我有一个 Tomcat Web 应用程序 它代表客户端执行一些内存和 CPU 密集型任务 这是正常现象 也是所需的功能 然而 当我运行 Tomcat 时 内存使用量会随着时间的推移飙升至 4 0GB 以上 此时我通常会终止该进程 因为它会扰
  • 为什么 Clojure 变量 arity args 根据使用而获得不同的类型?

    在回答中另一个问题 https stackoverflow com questions 26039461 does clojure have the c sharp equivalent of yield 26040454 comment4