首页 > 解决方案 > 无法获取宏的值:#'clojure.core/case

问题描述

我正在 Clojure 中的函数内创建一个函数,以模拟 Java 的对象概念,其中我的函数人充当构造函数。(只是想在 Clojure 中使用这个概念。)

(defn person [name age]
  (def p (fn [args & age]
    case args
     :set-name (person (first args) age)
     :set-age (person age)
    ;; :get-name (person (first args))
    ;; :get-age ()
)))

但我收到以下错误:

CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/case, compile:(null:2:8)

标签: clojure

解决方案


  1. 您(几乎总是)不应该def在另一个内部使用 adefdefn. Usingdef是一个全局声明,它应该(几乎)始终独立于源文件中。

请参阅Clojure for the Brave & True以获得在线介绍,或许多好书,例如Getting Clojure.

  1. 您忘记了周围的括号case

例子:

(case args ...)
  1. Usingcase是一个主要为 Java 对象互操作设计的特殊功能,并带有一些严重的限制(也称为“优化”)。恕我直言,使用它几乎总是更好cond

例子:

(cond
  (= :set-name args)   (person (first args) age)
  (= :set-age  args)   (person age)
  ...)

更新

问题之一case是它必须是编译时文字。但是,这并不明显,如果您尝试使用不符合定义的东西,也不会发出警告。然后,你只会得到一个无声的失败。此示例看起来应该返回"my vec",但失败并返回"default"

; "The test-constants are not evaluated.  They must be compile-time
; literals, and need not be quoted." 
(let [myvec [1 2]]
  (case myvec
    []             "empty vec"
    (vec '(1 2))   "my vec"
    "default"))
;=> "default"

因此,使用case会留下一个陷阱,准备好在没有警告的情况下破坏您的代码。


推荐阅读