我是Clojure的新手。该问题与this one有关,但有所不同。 说我嵌套了地图:
(def example
{:a {:b 2 :data [1 2 3] :something-that-uses-data ?}})
假设我要访问(-> example :a :b :data)
中的:something-that-uses-data
。是否必须使用与某些宏或关键字(例如(-> this :data)
之类的关键字)完全相同的方法来调用它?几个小时找不到任何相关内容。
答案 0 :(得分:0)
我认为您正在尝试模仿Clojure中的对象。对象具有将数据和处理该数据的功能打包在一起的类,但是在像Clojure这样的功能语言中,数据和功能是分开的。
因此,Clojure中的惯用方式是函数方法,它只是对不可变数据起作用的函数。 Clojure中唯一的OO功能是协议,用于多态。
我认为您在示例中想要的是:
(def example
{:a {:b 2 :data [1 2 3]}})
(defn something-that-uses-data [{{:keys [data] :a}}]
(do-work-with data))
您当然可以有一个包含数据和函数的映射,但是仅当函数不同并且您想在顺序上下文中应用这些函数时,该映射才有用。像这样...但是我只是在猜测您的上下文可能是什么。
(map (fn [[k v]
(let [data (:data v)
f (:somthing-that-uses-data v)]
(f data)))
collection-of-maps)
答案 1 :(得分:0)
我不确定我是否理解这个问题。您可以编辑以阐明所需的行为吗?
您可以通过3种方式访问Tupelo库中的深层数据结构。
使用tupelo.forest
处理树状数据结构。 See the docs,并确保观看视频。
您可以使用tupelo.core/destruct
,这是使用模板的get-in
的较高级版本。参见the examples here。
您可以对数据结构进行深度优先遍历,并使用walk-with-parents
跟踪每个节点的父级。参见the examples
和the docs。
您可以使用walk-with-parents
和walk-with-parents-readonly
进行此操作。考虑以下简单的嵌套数据结构:
(def data {:a 1 :b {:c 3}} )
我们可以遍历数据结构,记住从根到每个元素的路径。当我们到达元素3
时,我们具有以下父数据路径:
(walk-with-parents data <noop-intc>) =>
:parents => [ {:a 1, :b {:c 3}} ; the orig map
[:b {:c 3}] ; the MapEntry for key :b
{:c 3} ; the map where value 3
[:c 3] ] ; the MapEntry with value 3
:data => 3
因此拦截器将通过2个参数调用:
对于-readonly
变体,侦听器功能可以进行验证并在检测到问题时引发异常。对于非只读变量,返回值将替换数据元素。每个拦截器都是一个2元素映射,如下所示:
{:enter (fn [parents data] ...)
:leave (fn [parents data] ...) }