- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我试图了解 Clojure 对非尾部位置 recur
的保护是如何工作的。
如果编写这样的代码,Clojure 会抛出异常:
(def some_var (recur))
但是如果我评估动态创建的代码呢?
(def code '(recur))
(def some_var (eval code))
如果您尝试在 REPL 中运行这段代码,它似乎会无限循环。我预计它会抛出异常。
我的问题:
Clojure 什么时候检查 recur 是否在尾部位置?
我的第二个代码示例(在非尾位置动态执行的重复出现)的确切语义是什么?
最佳答案
您的 eval
调用实际上导致编译代码,其中 recur
确实 出现在尾部位置。
这是因为 eval
的实现方式——如果您将表单传递给 eval
,它是一个 Clojure 持久集合,但它看起来不像一个 >def
形式,它被包装在 fn
形式中,该 fn
形式是实际编译的,然后调用结果函数。
以下是如何将其应用于您的示例:
(eval '(recur))
;; does '(recur) look like a def form?
;; → no, so transform the above, in effect, to
((eval '(fn [] (recur)))
;; more precisely, before handing off `'(recur)` to lower-level
;; compilation methods, wrap it in `(fn [] …)`:
(fn [] (recur))
;; then immediately call the resulting function with no arguments
;; ultimate result: loop endlessly
如果你想知道这是在哪里发生的,请查看 clojure.lang.Compiler
的 public static Object eval(Object form, boolean freshLoader)
方法 - link to the code as of Clojure 1.8 .
请注意,出于同样的原因,目前(从 1.9.0-alpha14 开始)在内置 REPL 中键入 (recur)
也会无限循环。不同的 REPL 实现可能会或可能不会以防止这种情况的方式预处理输入表单,然后再将它们交给 eval
。
recur
的语义这些与 Alex Miller 链接到的官方文档、他的回答和评论中的解释完全相同。总而言之,recur
必须在建立recur
目标的表单中使用; loop
、fn
和reify
(内部方法实现)都是此类形式的示例。
上述语义是在编译时通过使用少量动态 Var 强制执行的,当它下降到为编译传递的顶级表单的各种子表单时,编译器会适本地绑定(bind)这些动态 Var。如果您想详细了解控制流程,请在 Compiler.java 中搜索 NO_RECUR
、LOOP_LABEL
和 LOOP_LOCALS
的用法。它的要点是,如果表单不在尾部位置,这些 Var 将绑定(bind)到表明在编译时是这种情况的值。
ClojureScript 使用的设置可能更容易遵循,尽管它基于相同的基本思想。参见 analyzer.clj (使用 v1.9 标签的稳定链接);特别是 *recur-frames*
和 disallowing-recur
。
关于recursion - Clojure 什么时候检查 recur 是否出现在尾部位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41666786/
我发现了一些令人费解的行为。给定一个包含 50 个日期的列表: structure(c("15513", "12830", "16503", "-3628", "15833", "13553", "4
我正在尝试创建单链表,但我不知道我做错了什么。 在插入元素 5、6、7、2、3、4 后,尾部应该是 4,但我得到的是 3,我不明白为什么。 这是我的代码: public void Insert(int
这是我的尾部代码(前 10 行): #include #include #include typedef char storage_datatype; #define MAXLINESIZE 1
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
是否有一种有效的方法可以从 List 中删除 X 元素的范围(例如尾部),例如LinkedList 在 Java 中? 显然可以一个一个地删除最后一个元素,这应该会导致 O(X) 级别的性能。至少对于
在之前的一篇文章我们介绍了《如何向php数组中头部和尾部添加元素》既然有添加元素,那么就有删除元素,今天这篇文章详细介绍如何删除数组中的头部元素和尾部元素,还有任意数组元素。 删除末尾元素:arr
在双向链表的实现中,我使用了典型的结构: struct node { void *data; struct node *prev; struct node *next; };
ECMA-335,III.2.4指定可以在递归函数中使用的tail.前缀。但是,我在C#和F#代码中都找不到它的用法。有使用in的示例吗? 最佳答案 您不会在当前的MS C#编译器生成的任何代码中找到
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
这个问题在这里已经有了答案: How to 'grep' a continuous stream? (13 个答案) 关闭 8 年前。 Tail 有以下选项: -f The -f opti
我试图弄清楚一旦我击中某个字符,如何从尾部修剪 Bash 中的字符串。 示例:如果我的字符串是这个(或任何链接):https://www.cnpp.usda.gov/Innovations/DataS
我试图弄清楚一旦我击中某个字符,如何从尾部修剪 Bash 中的字符串。 示例:如果我的字符串是这个(或任何链接):https://www.cnpp.usda.gov/Innovations/DataS
当我执行这段代码时,循环总是在第一次结束(即使 auth.log 的最后两行不包含“exit”),这意味着 $c总是得到一些字符串: while true; do c=$(tail -2 /v
我正在尝试编写一个“添加”函数,该函数接受节点中保存的值(表示为“n”),以及节点要添加到链表中的位置(表示为“pos”)。 我看到代码中有 3 个单独的添加函数 - addAtBeginning、a
为什么我不能得到“cd fjadf”? 程序总是向我显示 Bus error: 10... 我想用这个super_cut_tail()函数来截断用户指定的///fjdakf。但是为什么这个功能不能实现
有一个简化的表 mytable,其中列 ('id', 'mycolumn') 为 int 和 varchar(255 )分别。 在 mycolumn 中查找当前字符串具有最长公共(public)右侧部
这个问题已经有答案了: 已关闭13 年前。 Possible Duplicate: Get last n lines of a file with Python, similar to tail 你好
我想通过对写出的响应主体进行哈希处理来计算响应的实体标签。当我计算实体标签时,将实体标签添加到响应 header 已经太晚了。我想将实体标签添加到预告片中。我看到 net/http 包支持编写预告片,
我正在尝试通过 script.sh 从第 2 行到第 5 行打印文件 (myfile) 的内容。脚本无法从位置 2 打开文件。并且内容从第 1 行打印到第 4 行。以下是文件内容、命令和命令的输出。
在一个特殊的控制台上,我喜欢从/var/log/syslog 中过滤一些信息。这并不是很棘手: tail -f /var/log/syslog | awk '{print $2,$1,$9,$3,"\
我是一名优秀的程序员,十分优秀!