clojure - 一种收集 Clojure Let 表达式的所有绑定(bind)的方法

标签 clojure clojure-contrib

我发现自己正在编写一个函数,该函数传递封闭的 let 表达式中绑定(bind)的每个变量。此场景的简化形式(伪代码)为

(let [a 1 b 2 c 3 d 4 e 5 f 6]
  (do-something a b c d)
  (f a b c d e f g)
  (compute-another-thing a c))

而我想写一些更像......的东西

(let env-name [a 1 b 2 c 3 d 4 e 5 f 6]
   (do-something (take 4 env-name))
   (f env-name)
   (compute-another-thing a c))

也就是说,clojure 核心(或外部可靠的东西)是否提供了一个 let 变体,将所有绑定(bind)收集到一个具有名称的集合中?

最佳答案

解构将使您达到目标:

(let [[a b c d e f :as env-name] [1 2 3 4 5 6]]
   (apply do-something (take 4 env-name))
   (apply f env-name)
   (compute-another-thing a c))

请注意,使用环境名称调用函数时必须使用apply

对于更优雅的东西(例如您提议的形式),我认为您必须编写自己的宏。

更新:这是一个(经过非常简单的测试)宏,可以处理简单的情况:

(defmacro let-as 
  [as-bind-name bindings & body]
  (let [lhs-bindings (map first (partition 2 bindings))]
    `(let ~bindings
       (let [~as-bind-name [~@lhs-bindings]]
             ~@body))))

只要正常的 let 绑定(bind)的左侧是简单符号(即不使用解构),这应该可以满足您的要求。

一些 REPL 交互来说明:

core> (let-as env-name [a 1 b 2 c 3 d 4 e 5 f 6] (print env-name) (apply + env-name))
[1 2 3 4 5 6]
21

某些解构行为良好:

core> (let-as env-name [[a b] [1 2] [c d] [3 4]] (print env-name) (map first env-name))
[[1 2] [3 4]]
(1 3)

其他解构不是:

core> (let-as env-name [{:keys [a b]} {:a 1 :b 2}] (print env-name) (+ a b))
[{:keys [1 2]}]
3

这可以补救,但宏必须更复杂

关于clojure - 一种收集 Clojure Let 表达式的所有绑定(bind)的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25492156/

相关文章:

clojure - 你如何在clojure中通过键找到 map 集的交集?

java - 没有 Maven 的 Vaadin Clojure 小部件编译

clojure - 查找 clojure-contrib 库已移动到的位置

mysql - 如何编写带有嵌入式双引号的 Clojure 查询

Clojure:如何构建桌面 UI

function - 如何动态查找 Clojure 函数的元数据?

xml - 在 Clojure 的 XML 文件中插入 Zipper 树

clojure - 如何找到我的哪些依赖项正在下载特定的 jar?

configuration - 您希望如何安装 clojure 模块化贡献?

ubuntu - apt-get 是否可以在 Linux (ubuntu 10) 上安装 Clojure?