clojure - 无法获取宏的值:#'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)
解决方案
- 您(几乎总是)不应该
def
在另一个内部使用 adef
或defn
. Usingdef
是一个全局声明,它应该(几乎)始终独立于源文件中。
请参阅Clojure for the Brave & True以获得在线介绍,或许多好书,例如Getting Clojure
.
- 您忘记了周围的括号
case
:
例子:
(case args ...)
- Using
case
是一个主要为 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
会留下一个陷阱,准备好在没有警告的情况下破坏您的代码。
推荐阅读
- tsql - Split up a delete query
- ios - Is certificate relate with provisioning profile in iOS?
- ios - iOS 无法从 iTunes 获取准确的应用程序版本
- git - 搜索 git repo 文件的所有版本
- mysql - 在带有参数的存储过程中使用prepare语句时mysql中的语法错误
- python - Python中的最小二乘SVR回归
- javascript - 如何禁用/启用表单的提交按钮
- java - Java Get and Set returning value 0 on an operation
- amazon-web-services - AWS CloudFormation CI CD 管道字段由于访问被拒绝(服务:Amazon S3)
- bash - 运行 AWS CLI 时 Bash 脚本变量值发生变化