【问题标题】:Clojure collection atom with selected item带有所选项目的 Clojure 集合原子
【发布时间】:2021-01-31 18:40:40
【问题描述】:

在 Clojure(实际上是 ClojureScript)中完成以下任务的最佳方式是什么:

  • 一个可变的元素集合xs,每个类型为TT 是一个映射,如果我们想具体一点的话)
  • 其中一个“选定元素”x,在各种xs 或“未选定”状态之间交替。所选项目的数量为 1 或 0。
  • xsx 将有事件监听器监听它们:一些监听 xs 的任何变化;有些人会听x 的任何变化。 (也就是说,它们监听所选项目状态的更新,以及选择哪个项目的切换。)(我实际上使用 React 的 Reagent 包装器,所以这会影响组件何时更新。 )
  • 编辑x的方法(不需要编辑未选中的xs,但需要能够添加新的xs
  • 给定xs 中的一个元素,选择它的方法。 (包括选择“无”的情况)

到目前为止我想到的可能性:

  1. 使xs 成为Ts 的向量的原子,并确保每个T 元素都知道自己的索引。将x 替换为x_idx,它存储所选项目的索引(或nil)。选择一个元素只是意味着获取它的索引并将x_idx 更改为该索引,这两者都是恒定时间操作。这样做的缺点是它使结构不那么优雅和简单:我总是传递所选项目的 index,而我想做的每一个操作都必须使用索引来代替项目本身,如它所愿。由于我的T 对象很小,所以如果有一个T 类型的“选定对象”变量会更令人愉悦。
  2. xs 设为原子向量,将x 设为存储T 的原子。现在xT,这很好,但是当我想更新有关x 的信息时,我必须两次调用reset!swap!:一个用于x,一个用于xs 中的元素,x 代表。不优雅的原因显而易见。我必须快速连续执行这些操作,否则数据会出现不一致:在两次调用之间,监听xs 的事件监听器将看到选定的项目处于一种状态,而监听@987654356 的事件监听器将看到@ 会在另一个状态下看到它。
  3. T 元素一个字段来判断它们是否被选中,并去掉x。如果可以一次选择多个项目,这将是正确的,但由于只能选择一个项目,它只会让我每次想要选择的项目时都进行线性搜索,这很糟糕。

这个问题的重点不是解决某些特定问题(上述任何可能性都适用于我正在从事的小型项目的范围),而是要了解 Clojure 数据结构。这似乎是一种很常见的情况,周围会有一些结构。欢迎使用“您应该尝试完全回答一个不同的问题......”这样的回答。

【问题讨论】:

  • 您可能希望提供一些代码示例,说明您将进行哪些函数调用、预期结果等。到目前为止,您为解决此问题编写的最佳代码是什么样的?
  • 1.地图是不可变的。 2. 如果这个数据结构要支持 React,让它可变可能不是最好的主意。 3. 事件监听器?如何?我假设这些不是原始 DOM 节点。 4. 这整个事情听起来像是对选择元素的抽象,这就是你想要的吗? 5. 你说得对,这整件事听起来有点离谱(不完全存在,但以某种方式歪曲)。你能给我们一些实际的代码以及为什么它可以工作或不工作吗?
  • “这个问题的重点不是解决某个特定问题”,这就是 SO 的全部意义所在。这应该分成五个问题,每个问题都有你的研究和尝试。此外,Hickey(Clojure 的创建者,icydk)在 p. 上讨论了 Clojure 的数据结构。他 2020 年论文中的 6 篇,"A History of Clojure"
  • @JaredSmith 映射不是可变的,但如我所述,其状态是映射集合的原子是可变的。我同意我的问题可以通过一些代码来改进。

标签: data-structures functional-programming clojurescript reagent


【解决方案1】:

您(我)想研究cursors 和reactions,这是试剂原子的两个更高级的功能。它们可用于在其中包含自动更新的集合和选定元素。例如,请参阅here

假设您有一个 r/atom 持有对象向量,并且您想要一个可以更改且可直接编辑的选定对象。实现这一点的一种方法是保留一个原子来存储所选项目的索引,然后

(defn my-get-set
  ([_k] (@vector-of-items @idx-of-selected-item))
  ([_k v] (reagent.core/rswap! my-state-vector assoc @idx-of-selected-item v)))

(def selected-item (reagent.core/cursor my-get-set []))

编辑:reagent.core/cursor my-get-set nil 更改为reagent.core/cursor my-get-set []。前者会导致问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-30
    • 2020-07-01
    • 2016-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多