2024 年 Clojure 状况调查 中分享您的想法!

欢迎!有关如何使用本站点的更多信息,请参阅关于页面。

0
Clojure
问题描述

假设我想使用 let 创建多个绑定然后执行一个体。我可以这样轻松地做:

(let [a 1
      b (inc a)
      c (* b b)]
  [a b c])


但是,如果我想使用 if-let 做类似的事情,我必须通过嵌套来实现,因为 if-let 每次只接受一个绑定。

(if-let [a 1]
  (if-let [b (inc a)]
    (if-let [c (* b b)]
      [a b c]
      "error")
    "error")
  "error")


这非常不优雅,因为
1) 它的阅读性不如所有绑定都在同一缩进级别的简单。
2) 否则子句被多次重复。
3) 否则子句在不同的上下文中进行评估,具体取决于哪个绑定失败。如果 a 已经被绑定呢?如果 if-let 覆盖了 a,而 b 没有被绑定,则否则子句将执行一个与第一次 if-let 中 a 未被覆盖时不同的 a 值绑定。(以下代码示例)

我想能这样写 instead

(if-let [a 1
         b (inc a)
         c (* b b)]
  [a b c]
  "error")
=> [1 2 4]

(let [a :original]
  (if-let [a :shadowed
           b false]
          a a))
=> :original


我还想能够用 when-let、if-some 和 when-some 做类似的事情。

*建议:*

我重新编写了那些宏,以便能够处理多个绑定。如果只提供了一个绑定,它们的行为保持相同。如果提供了多个绑定,它们只能在所有绑定均通过的情况下执行体。在 if-let 或 if-some 中的某些绑定通过而某些绑定失败的情况下,不应有任何一个绑定泄漏到否则子句中。

*修补程序:*

- clojure-core v2 8-3-2017.patch - 包含宏更新的 Clojure 修补程序。对于 if-let 和 if-some,我必须添加一些额外的逻辑,以防止在有些绑定通过而有些绑定失败的情况下,它们将绑定泄漏到否则子句中。它还包括围绕每个宏的一些额外测试。
- core.specs.alpha.patch - 核心规范 alpha 修补程序,包含对核心规范的等效更新

5 个回答

0

评论者:alexmiller

这与CLJ-2007有什么关系?

0

评论者:justinspedding

我在评论中发布了该任务的解决方案,随后您发布了有关票务正确格式的帖子,并提供了创建指南的链接。我认为这意味着您希望创建遵循约定的票据。

此外,此票据是关于修改现有宏的。CLJ-2007是关于创建两个新宏:if-let*和when-let**。

0

评论者:gshayban

值得看看 JVM 意图如何使用测试和分解的内省。布赖恩·戈茨在最近的关于模式匹配的演讲中谈到了这一点(链接:1)

(链接:1) https://www.youtube.com/watch?v=n3_8YcYKScw

0

评论者:justinspedding

当if-let和if-some没有给出绑定时,简化生成的补丁代码

0
参考:https://clojure.atlassian.net/browse/CLJ-2213(由justinspedding报告)
...