Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.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
在Clojure中,如何分解贴图的所有键?_Clojure - Fatal编程技术网

在Clojure中,如何分解贴图的所有键?

在Clojure中,如何分解贴图的所有键?,clojure,Clojure,在clojure中,可以按如下方式分解贴图的某些键: (let [{:keys [cpp js]} {:cpp 88 :js 90}] (println js); 90 (println cpp); 88 ) 有没有办法分解地图的所有键 可能是这样的: (let [{:all-the-keys} {:cpp 88 :js 90}] (println js); 90 (println cpp); 88 ) 不是真的,这也不是个好主意。想象一下: (let [{:

在clojure中,可以按如下方式分解贴图的某些键:

(let [{:keys [cpp js]} {:cpp 88 :js 90}] 
   (println js); 90
   (println cpp); 88
 )
有没有办法分解地图的所有键

可能是这样的:

(let [{:all-the-keys} {:cpp 88 :js 90}] 
   (println js); 90
   (println cpp); 88
 )

不是真的,这也不是个好主意。想象一下:

(let [{:all-the-keys} m]
  (foo bar))
foo和bar是全球性的吗?当地人?您应该从m中提取的密钥?如果m有时包含一个foo键,并且foo也是一个全局函数,那么该代码应该怎么做?有时调用全局函数,有时调用存储在m中的函数


忽略技术问题(可以克服),这对可读性和可预测性来说确实是一场灾难。只需明确说明你想拔出什么样的钥匙;如果您经常想拔出相同的十个键,您可以编写一个简单的宏,如
(带person p body)
,简化您的常见情况。

您可以编写一个宏来完成此操作(有效地创建一个迷你DSL),但出于以下原因,我认为这不是一个很好的主意:

  • 为了创建正确的编译时文本js和cpp,需要在编译时对映射进行分解。这对于您可以使用它做的事情来说是非常有限的(例如,您必须提前指定键,并且它不能在高阶函数中使用)
  • 当一个更简单的方法可以完成这项工作时,宏通常是一个坏主意(见下文)
我建议您在地图上使用一个简单的循环:

(let [my-map {:cpp 88 :js 90}]
  (doseq [[k v] my-map]
    (println v)))
请注意:

  • 您可以使用如上所述的解构来从每个映射条目中提取键
    k
    和值
    v
  • 我使用而不是因为它是非惰性的,在这个例子中,似乎您使用循环只是为了产生副作用
  • 相反,如果您想要一个惰性的值序列(8890),那么将是合适的

这个问题很老了,所以你可能已经忘记了,但是当我尝试做同样的事情时,它出现在谷歌上,所以如果我发布我的解决方案,它可能会帮助其他人

(defmacro let-map [vars & forms]
  `(eval (list 'let (->> ~vars keys
                         (map (fn [sym#] [(-> sym# name symbol) (~vars sym#)]))
                         (apply concat) vec)
               '~(conj forms 'do))))
这基本上将map
{:cpp 88:js 90}
转换为绑定形式
[cpp 88 js 90]
,然后构造一个
let
绑定,同时执行一些评估柔术,以确保这在运行时发生

(def test-map {:cpp 88 :js 90})
(let-map test-map
  (println js)
  (println cpp))
;=> 90
;=> 88

哦,cmon,这是唯一一个真正回答标题中问题的答案。谢谢。这是一个非常聪明的宏。让我们花一点时间来认识它的独创性,然后承诺我们永远不会在生产代码中编写类似的东西。这看起来可能不是最佳实践,但我甚至认为这种构造存在有效的用例。它实际上不起作用<代码>(def测试映射{:cpp(Object.)})爆炸
无法在代码中嵌入对象