3

我有一个产生函数的宏。我知道最好的做法是使用 gensyms 来确保不会发生命名冲突。所以我想知道对于宏将定义的函数的参数名称是否需要遵循这个原则?

这是我的宏供参考:

(defmacro defroute
  [routename uri meths handler]
  `(defn ~routename
    [~'req]
    (let [req-meth# (:request-method ~'req)
          bad-meth# (nil? (some #(= req-meth# %) ~meths))
          any-meth# (= ~meths [:any])]
      (if (:uri ~'req)
        (if (and (route-matches ~uri ~'req) (and bad-meth# (not any-meth#)))
          (method-not-allowed req-meth# (get-allowed ~meths))
          (let [params# (route-matches ~uri ~'req)]
            (if (nil? params#)
              ~'req
              (~handler (assoc ~'req :route-params params#)))))
        ~'req))))

如您所见,我目前没有使用 gensym 作为req参数。我最初然后想知道是否有必要。无论如何,感谢您的阅读。

4

1 回答 1

2

在这种情况下,使用req是相对安全的,因为它建立了一个本地范围。作为函数参数,它将隐藏调用命名空间中与符号 req 的任何现有绑定,而不会损坏它们。这样做的代价是,如果有人试图将名称 req 用于任何其他参数,例如 handler,他们可能会感到有点意外。在我看来,这段代码并没有错,尽管它在某些情况下确实违反了最小化原则。我认为没有任何理由不使用自动生成符号,req因为它只是添加几个#s 的工作。

于 2013-04-02T19:44:08.513 回答