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

欢迎!请参阅关于页面以获取更多关于工作方式的详细信息。

0

我在尝试Brave Clojure(第8章练习3)中的练习。我简化它以了解我的问题所在。

请考虑以下配置

(def person {:first-name "Louis"
             :last-name "Bourvil"
             :age 32
             :city "Nantes"})

我希望能够做到以下操作

(create-func c-age :age)
(c-age person)

我知道这一点是可行的

(defmacro create-func [func-name attr] `(def ~func-name ~attr))

但我试图用函数实现,不明白为什么这个操作不起作用

(defmacro create-func [func-name attr] `(defn ~func-name [person] (~attr person)))
(create-func c-age :age)
; Syntax error macroexpanding clojure.core/defn at (REPL:1:1).
; user/person - failed: vector? at: [:fn-tail :arity-n :bodies :params] spec: 
:clojure.core.specs.alpha/param-list
; (user/person) - failed: Extra input at: [:fn-tail :arity-1 :params] spec: 
:clojure.core.specs.alpha/param-list

(来自REPL)

您看到我的错误在哪里了吗?

1 答案

0

已选中
 
最佳答案
(defmacro create-func [func-name attr] `(defn ~func-name [person] (~attr person)))
(create-func c-age :age)

当您这样写时,它会展开为

(defn c-age [user/person] (:age user/person))
Syntax error macroexpanding clojure.core/defn at (/tmp/form-init14482279258588584188.clj:1:1).
user/person - failed: vector? at: [:fn-tail :arity-n :bodies :params] spec: :clojure.core.specs.alpha/param-list
(user/person) - failed: Extra input at: [:fn-tail :arity-1 :params] spec: :clojure.core.specs.alpha/param-list

为了避免这种情况,您应该这样写

(defmacro create-func [func-name attr] `(defn ~func-name [person#] (~attr person#)))

或者使用其他方式来不在参数名称中使用限定符号。

为“获取器”创建宏是Clojure中的反模式。
如果您想要访问一个字段,只需直接访问它。
此外,def-macros通常可以写成函数。

(def c-age (im-not-a-macro :age))
by
确实非常感谢!这只是Brave clojure的一个练习...
欢迎来到Clojure问答社区,在这里您可以向Clojure社区的成员提问并获取答案。
...