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

欢迎!请查看关于页面以获得更多关于如何使用此页面的信息。

0
错误
以下是您可以粘贴到repl中的实现。希望得到反馈


(defn ^{:private true} local-bindings
  "生成局部变量名称与其值的映射表。"
  [env]
  (let [symbols (map key env)]
    (zipmap (map (fn [sym] `(quote ~sym)) symbols) symbols)))

(defmacro assert
  "评估表达式,如果表达式不评估为
 逻辑真则抛出异常。"
  {:added "1.0"}


  [x]
  (when *assert*
    (let [bindings (local-bindings &env)]
      `(when-not ~x
           (let [sep# (System/getProperty "line.separator")]
                                          (throw (AssertionError. (apply str "Assert failed: " (pr-str '~x) sep#
                                          (map (fn [[k# v#]] (str "\t" k# " : " v# sep#)) ~bindings)))))))))

15 答案

0

评论由:导入器制作

fogus说:哎呀,但是它完全失败了:(let (绑定: x 1 y 2 z 3 a 1 b 2 c 3) (assert (= (绑定: x y) (绑定: a c)))。所以,除非你需要真正的复杂化,否则最好只是打印出所有局部变量。
:f

0

评论由:导入器制作

http://www.assembla.com/spaces/clojure/tickets/415 转换而来

0

评论由:导入器制作

alexdmiller说:为了说明,我尝试了一个简单的例子

`用户=> (let [a 1 b 2] (assert (= a b)))

<编译器异常 java.lang.AssertionError: Assert失败: (= a b)

a: 1
b: 2
`

0

评论由:导入器制作

jawolfe说:另请参阅以下评论

http://groups.google.com/group/clojure-dev/browse_frm/thread/68d49cd7eb4a4899/9afc6be4d3f8ae27?lnk=gst&q=assert#9afc6be4d3f8ae27

关于这个问题的另一个建议:除了/代替打印局部变量,为什么不把它们保存在某处呢?例如,可以将变量 assert-bindings 绑定到局部变量的映射中。这样,您就不会遇到无限的/非常大序列,并可以使用户对错误值进行更详细的调查(特别是在某些局部变量打印得不够透明时非常有用)。

0

评论由:导入器制作

stuart.sierra说:我愿意捐赠另一种方法
http://github.com/stuartsierra/lazytest/blob/master/src/main/clojure/lazytest/expect.clj

0
_评论由:importer_ 制作

fogus说:如果您这样做确实有点奇怪
(let [x 1 y 2 z 3 a 1 b 2 c 3] (assert (= x y)))
java.lang.AssertionError: Assert失败: (= x y)
 x: 1
 y: 2
 z: 3
 a: 1
 b: 2
 c: 3
 (无源文件)
</code></pre>

所以或许可以稍微修改一下
<pre><code>(defmacro assert
  "评估表达式,如果它不评估为逻辑真,则抛出异常。"
  {:added "1.0"}


  [x]
  (when *assert*
    (let [bindings (local-bindings &env)]
      `(when-not ~x
         (let [sep#  (System/getProperty "line.separator")
               form# '~x]
           (throw (AssertionError. (apply str "Assert失败: " (pr-str form#) sep#
                                            (map (fn [[k# v#]]
                                                 (when (some #{k#} form#)
                                                         (str "\t" k# " : " v# sep#)))
                                               ~bindings)))))))))
</code></pre>

所以现在它是这样的。
<pre><code>(let [x 1 y 2 z 3 a 1 b 2 c 3] (assert (= x y)))
java.lang.AssertionError: Assert失败: (= x y)
 x: 1
 y: 2
 (无源文件)

:f

0
_ 评论由:jweiss 发表_

对于 fogus 最后一条评论的一个修改,我实际上正在使用。你在使用 'some' 来检查局部变量是否以这种形式使用之前,需要先将引用形式展平。

(defmacro assert
  "评估表达式,如果它不评估为逻辑真,则抛出异常。"
  {:added "1.0"}


  [x]
  (when *assert*
    (let [bindings (local-bindings &env)]
      `(when-not ~x
         (let [sep#  (System/getProperty "line.separator")
               form# '~x]
           (throw (AssertionError. (apply str "Assert失败: " (pr-str form#) sep#
                                            (map (fn [[k# v#]]
                                                         (when (some #{k#} (flatten form#))
                                                         (str "\t" k# " : " v# sep#)))
                                               ~bindings)))))))))

0

评论由:stu 发表_

我将推迟这个,直到我们有更多关于错误处理的讨论。(例如,可以考虑让所有从 Clojure 抛出的异常都可以访问局部变量。

当我的梦幻破灭时,我将在下一个版本之前回来并筛选这个。

0
_ 评论由:stu 发表_

为什么试图猜测某人想对局部变量(或任何其他上下文)做什么,当你可以指定一个回调(见下文)。在上周我有一个在 CI 箱子中失败的测试用例时,这会很有用,那时没有可供使用的调试器。

Rich,冒着重复的风险,我仍然认为这是一个好主意。调试器并不总是可用,这是一个 Lisp 内在能力比其他环境提供更好信息的例子。如果你想要下面代码的补丁,请标记等待我的反馈,否则请拒绝这个工单,这样我就不再关注它了。:-)



(def ^:dynamic *assert-handler* nil)

(defn ^{:private true} local-bindings
  "生成局部变量名称与其值的映射表。"
  [env]
  (let [symbols (map key env)]
    (zipmap (map (fn [sym] `(quote ~sym)) symbols) symbols)))

(defmacro assert
  [x]
  (when *assert*
    (let [bindings (local-bindings &env)]
      `(when-not ~x
         (let [sep#  (System/getProperty "line.separator")
               form# '~x]
           (if *assert-handler*
             (*assert-handler* form# ~bindings)
             (throw (AssertionError. (apply str "断言失败:" (pr-str form#) sep#
                                             (map (fn [[k# v#]]
                                                   (when (some #{k#} (flatten form#))))
                                                             ((str "\t" k# " : " v# sep#)))
                                                 ~bindings))))))))))
0
by

Comment made by: jweiss

A slight improvement I made in my own version of this code: flatten does not affect set literals. So if you do (assert (some #{x} (link: a b c d))) the value of x will not be printed. Here's a modified flatten that does the job

(defn symbols [sexp] "Returns just the symbols from the expression, including those inside literals (sets, maps, lists, vectors)." (distinct (filter symbol? (tree-seq coll? seq sexp))))

0
by

Comment made by: jafingerhut

Attaching git format patch clj-415-assert-prints-locals-v1.txt of Stuart Halloway's version of this idea. I'm not advocating it over the other variations, just getting a file attached to the JIRA ticket.

0
by

Comment made by: michaelblume

Previous patch was incompatible with CLJ-1005, which moves zipmap later in clojure.core. Rewrote to use into.

0
by

Comment made by: michaelblume

Both patches are somehow incompatible with CLJ-1224. When building my compojure-api project I get

`
Exception in thread "main" java.lang.UnsupportedOperationException: Can't type hint a primitive local, compiling:(schema/core.clj:680:27)

at clojure.lang.Compiler.analyze(Compiler.java:6569)
       ...
at clojure.main.main(main.java:37)

Caused by: java.lang.UnsupportedOperationException: Can't type hint a primitive local

at clojure.lang.Compiler$LocalBindingExpr.<init>(Compiler.java:5792)
at clojure.lang.Compiler.analyzeSymbol(Compiler.java:6929)
at clojure.lang.Compiler.analyze(Compiler.java:6532)
... 299 more

Failed.
`

0
by

Comment made by: jafingerhut

Michael, are you finding these incompatibilities between patches because you want to run a modified version of Clojure with all of these patches? Understood, if so.

如果你在寻找彼此不兼容的补丁对,我建议选择不同的爱好:-) 平均每月大约有9个补丁被应用,因此应该有足够的时间在之后解决它们之间的不一致性。

0
参考: https://clojure.atlassian.net/browse/CLJ-415(由 alex+import 报告)
...