【问题标题】:Looping through a "let"-list in Clojure?在 Clojure 中循环一个“let”列表?
【发布时间】:2012-12-27 18:39:56
【问题描述】:

如果我有一个未知数量的参数,我想用“let”相互绑定,例如:

let [a "hello" b 55 ]

如果我在函数/宏或类似函数中绑定 let 并且我想在列表中循环,我该怎么做?

请注意,在 let 中有 4 个元素,但我只想循环遍历“键”。一个使用示例可能是检查绑定到键的值是否是像 b 这样的数字,即 55

编辑:例如: 请注意,以下内容非常糟糕,但仅用于解释问题:

(defn func [& arguments] 
 (let [ ~arguments] ((println "omg no way!") (for [x let-list] (number? x (println "roar") )))

输入: (func [a "你好" b 55]

所以基本上: 我想要一个功能:

  • 将参数绑定到某种形式的列表,例如:[a b]
  • 打印“天哪!”) - 不应该是循环的一部分,应该只在函数中打印一次
  • 某种循环,例如 for 循环,它遍历“let-list”,因此它会:“a, is a number? no, is b number? yes, print "roar"

输出: 天哪,没办法 怒吼

再一次: 我想知道是否有一种方法可以访问函数中的 let 中的关键字。正如 for 循环所示,我想访问每个单独的元素并使用该元素执行操作。如果我使用 (for [x arguments] 代替,它会给出: 天哪,没办法, 怒吼 怒吼 (因为 b 与 55 绑定,所以它是一个数字,但 55 也是一个数字,但没有必要使用 55,因为 55 已经与 b 绑定)

【问题讨论】:

  • 听起来你想要的是looprecur:clojure.org/special_forms#Special Forms--(loop [bindings* ] exprs*)
  • 输入和输出的例子在这里会有很大帮助
  • 这看起来可以用地图更好地实现。但我同意@ArthurUlfeldt 的观点,即一个有上下文的例子真的会帮助我们帮助你。
  • 看起来你想要的是(map second (partition 2 arguments))

标签: clojure let


【解决方案1】:

这里是一个宏示例,它接受一个交替名称和值的列表,将它们绑定在一个 let 中,然后通过引入一个名为 ' 的符号保存它刚刚创建的绑定的映射 locals' 将本地名称映射命名为本地值。

(defmacro anaphoric-let [alternating-symbols-and-values & body]
  `(let [~@alternating-symbols-and-values
         names# (quote ~(flatten (partition 1 2 alternating-symbols-and-values)))
         values#  ~(vec (flatten (partition 1 2 alternating-symbols-and-values)))
         ~'locals (zipmap names# values#)]
     ~@body))

任何被称为anaphoric-let 的表达式都可以使用locals 名称中的值。

user> (anaphoric-let [a 1 b 2 c 3 d 4] [a locals])
[1 {d 4, c 3, b 2, a 1}]

将值保存在映射中之后 用 let 定义它们并在正文之前防止多次执行和其他不卫生宏的罪过。

然后可以使用此地图根据当地人做出决策:

user> (anaphoric-let [a 1 b 2 c 3 d 4 e "cat"] 
        (map (fn [[local val]] 
               (str local " is " (if (number? val) val "woof"))) 
              locals))
("e is woof" "d is 4" "c is 3" "b is 2" "a is 1")

或:

user> (anaphoric-let [a 1 b 2 c 3 d 4 e "cat"] 
        (println "omg no way!") 
        (dorun (for [x (vals locals)] 
                 (if (number? x) (println "roar")))))
omg no way!                                                                                                                                                    
roar                                                                                                                                                           
roar                                                                                                                                                           
roar                                                                                                                                                           
roar                                                                                                                                                           
nil

ps: anaphoic 宏是任何将名称引入其创建的代码中的宏,该名称在传递给它的代码中不存在。

【讨论】:

    猜你喜欢
    • 2017-06-04
    • 2010-11-06
    • 2016-05-14
    • 2017-06-10
    • 2012-01-29
    • 2014-06-19
    • 2014-03-21
    • 2015-10-18
    • 2015-06-04
    相关资源
    最近更新 更多