Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Map 存储分解映射以供以后使用_Map_Clojure_Destructuring - Fatal编程技术网

Map 存储分解映射以供以后使用

Map 存储分解映射以供以后使用,map,clojure,destructuring,Map,Clojure,Destructuring,我一直在努力让这项工作与报价,报价拼接,评估,以及任何其他我能想到的,但没有运气到目前为止。我理解为什么它不起作用——它被视为一张地图,它试图评估a、b、和c——而不是如何绕过它 (def destructor {a :a b :b c :c}) ; CompilerException java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(:1:15) (let [destruct

我一直在努力让这项工作与报价,报价拼接,评估,以及任何其他我能想到的,但没有运气到目前为止。我理解为什么它不起作用——它被视为一张地图,它试图评估
a
b
、和
c
——而不是如何绕过它

(def destructor {a :a b :b c :c})
; CompilerException java.lang.RuntimeException: Unable to resolve symbol: a in this context, compiling:(:1:15)

(let [destructor my-map]
  'etc)

我有一个相当复杂的分解图,我正在考虑使用几次,所以把它藏在某个地方似乎是个好主意。也许有更好的方法可以实现这一点?

好主意,但你不能完全用这种方法来实现,因为你想要存储的东西实际上不是一个值,所以你不能将它存储在变量中

相反,您可以定义一个宏,在其展开中包含以下内容:

(defmacro with-abc [abc & body]
  `(let [~'{:keys [a b c]} ~abc]
     ~@body))

(with-abc foo
  (...use a, b, and c...))

类似于@amalloy的回答也是我的第一直觉,这可能是我的方向。也就是说,可能值得考虑一个普通的高阶函数:

(defn destruct
  [{a :a b :b c :c} f]
  (f a b c))

(destruct my-map
          (fn [a b c]
            (println a)
            (println b)
            (println c)))

它有点刺耳,您每次都必须命名绑定,但您可以避免潜在的卫生问题,并且根据元编程的舒适程度,它更容易组合起来。

您需要引用破坏模式

(def my-destructor '{a :a b :b c :c})
您可以使用引号/取消引号级别来实现这一点,但是使用一个小的辅助函数更容易看到

(defn- with-destructor* [binding & body] 
  `(let ~binding ~@body))
eval
发生在“编译”时(在宏扩展期间)

如图所示

(macroexpand-1 '(with-destructor [my-destructor {:a 1 :c 3}] (+ a c)))
;=> (clojure.core/let [{a :a, b :b, c :c} {:a 1, :c 3}] (+ a c))
结果

(with-destructor [my-destructor {:a 1 :c 3}] (+ a c))
;=> 4

let子句中看起来很滑稽的
~'
是这样的:a、b和c不会得到语法引号限定的名称空间。我认为这是必要的,但我现在不是在一台真正的电脑前,所以如果有人看到它,你就不能随意编辑。非常好。我不能使用
:keys
(不过很高兴将其视为一个示例),因为我有一个“相当复杂的分解图”(即多个级别),但在我的图中交换效果非常好。我曾经尝试过使用宏,但是——尽管已经成功地使用了很多次——我想我还没有完全意识到将所有的东西都传递进来,并得到一个全新的、完全改变的东西。谢谢@阿马洛伊:说实话,你是对的,
~”
是必要的。我对它进行了测试,它可以正常工作,但是去掉
~”
会导致
java.lang.RuntimeException:不能让限定名:user/a
。是的,我想避免命名东西,因为我的地图不仅包含几十个东西,而且它们还处于几个不同的嵌套级别。不过,在可能的情况下,尝试找到功能性路线是很好的。谢谢,明白了。听起来宏就是这样。带析构函数的
的定义根本没有理由使用
eval
。它的主体应该是
(与析构函数一起应用*[destructor form]body)
。当然,如果你用析构函数*
中删除vararg,你可以避免
应用
。@amalloy也许我遗漏了什么,但我相信你的建议只适用于
中的字面析构函数表达式(用析构函数[{a:ab:bc:c}{a 1:c3})(+ac))
,但是没有一个像问题中那样存储在var中,我明白了。您试图让用户提供
析构函数
,而不是修复特定宏。我很困惑,因为您将宏参数命名为与var相同的参数,并且我认为宏是指var。
(with-destructor [my-destructor {:a 1 :c 3}] (+ a c))
;=> 4