首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >让表单:如何访问宏中的非结构化符号?

让表单:如何访问宏中的非结构化符号?
EN

Stack Overflow用户
提问于 2014-04-22 10:17:38
回答 2查看 504关注 0票数 6

我正在尝试编写一个宏,它扩展为一个destructuring的let表单。我的问题是,我想要在let形式中定义的符号列表,包括那些通过重构获得的符号。

用例

我试图将这类行为考虑在内,例如,验证:

代码语言:javascript
复制
(let [a (foo bar)
      {x :x,
       y :y,
       {u :u, v: v :as nested-map} :nested} some-map]
  (and x y nested-map u v ; testing truthiness
       (valid-a? a)
       (valid-x? x)
       (valid-y? y)
       (valid-nested? nested-map)
       (valid-u-and-v? u v)
       ))

提出的解决方案

通过某种and-let宏来实现这一点将是非常好的,我可以这样称之为:

代码语言:javascript
复制
(and-let [a (foo bar)
          {x :x,
           y :y,
           {u :u, v: v :as nested-map} :nested} some-map]
         (valid-a? a)
         (valid-x? x)
         (valid-nested? nested-map)
         (valid-u-and-v? u v))

我错过了什么,

但我缺少某种方式来访问在let表单中绑定的符号列表。如果我有类似于list-bound-symbols函数的东西,我可以这样做:

代码语言:javascript
复制
(defmacro and-let
  "Expands to an AND close that previouly checks that the values declared in bindings are truthy, followed by the tests."
  [bindings & tests]
  (let [bound-symbols (list-bound-symbols bindings) ;; what I'm missing
        ]
    `(let ~bindings
       (and 
         ~@bound-symbols
         ~@tests)
     ))) 

有人知道我该怎么做吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-04-22 10:25:23

析构由clojure.core/destructure函数处理。它是公开的,因此我们可以自己调用它,并提取所有本地用户的名称,包括那些命名用于破坏的中间结果的名称:

代码语言:javascript
复制
(defmacro and-let [bindings & tests]
  (let [destructured (destructure bindings)]
    `(let ~destructured
       (and ~@(take-nth 2 destructured)
            ~@tests))))

似乎奏效了:

代码语言:javascript
复制
(let [foo nil]
  (and-let [a 1
            [b c] [2 3]]
    (nil? foo)))
;= true
票数 5
EN

Stack Overflow用户

发布于 2014-04-22 11:30:56

您可以通过一个直接处理映射的函数来完成这些操作。

代码语言:javascript
复制
(defn validate [vm ; validation map
                dm ; data map
                ]
  (and
    (every? identity (map #(% dm) (flatten (keys vm))))
    (every? identity (map (fn [[k vf]]
                            (if (vector? k)
                              (apply vf (map #(% dm) k))
                              (vf (k dm))))
                          vm))))

例如

代码语言:javascript
复制
(validate {:s string?, :n number? :m number? [:m :n] > } {:s "Hello!", :m 5, :n 3})
; true

(validate {:s string?, :n number? :m number? [:m :n] > } {:s "Hello!", :m 5, :n 6})
; false

(validate {:s string?, :n number? :m number? :u \b [:m :n] > } {:s "Hello!", :m 5, :n 6})
; false

您可以事先将示例中的任何无关变量( a )添加到映射中。这将不必要地测试a的真实性。没有造成伤害?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23216696

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档