我正在写一个重帧应用程序,它模拟了一个棋盘游戏,其中我有一个包含单元数组的棋盘结构,类似于:
{... :board-cells [{:name "cell-1" :material #object} {:name "cell-2" :material #object} ...]}虽然re-frame支持使用像(db :board-cells)这样很好的关键字语法来获取“自然”子结构,但我已经厌倦了每次想要获取材料时都要编写整个“下钻”查询:(get (nth (db :board-cells) index) :material)。这也有将数据库的物理布局与应用程序逻辑紧密耦合的缺点。如果我决定改变我的数据库结构怎么办?然后我必须更新十个不同的位置,而不是只更新一个。
有没有一种官方的方法来创建一个“虚拟查询”,这样我就可以得到一个类似于(db :get-nth-mat n)的材质,其中n是board-cells数组中的单元格编号?我以为我可以在db.cljs和reg-sub上做这件事,但它似乎不起作用。是的,我可以创建自己的getter:
(defn get-material [db index]
(get (nth (db :board-cells) index) :material))并将其命名为(println "mat-4=" (cell/get-material db 4)),但它不如(db :get-nth-mat n)方便或友好
非常感谢。
发布于 2020-01-03 17:28:11
db只是一个地图,这个“特征”与重帧无关,但每个地图都是一个函数,关键字也是一个函数。所以当你使用(map something)或(:keyword something)时,你实际上是在使用(get map something)和(get something :keyword)。
因此,除了以不同的方式访问/迭代您的数据(例如doseq、for、map等)之外,真的没有什么“捷径”--假设您要逐个单元格地渲染网格;这样您就完全摆脱了基于索引的访问。
否则,我会使用像您这样的专用函数,但更愿意将其命名为material-by-idx (在OO中,将函数命名为get和set类似访问器是相当不常见的(但也有它的位置,例如,设置状态修改))。
正确命名,理想情况下是纯函数,正确地做一件事是函数式和Lisp编程中一个重要的构建块。通常,必须键入更多内容的缺点可以通过更高级的编程范例来缓解,比如线程或部分应用程序,或者作为最后的手段,宏。
您可以使用get-in将其整理一下:
(defn material-by-idx [db idx]
(get-in db [:board-cells idx :material]))例如,你现在可以在你的循环中使用类似这样的东西,如果你在其中看到了价值:
(let [mat-at (partial material-by-idx db)]
(mat-at 5))顺便说一句:你希望的(db :get-nth-mat n)版本实际上是可以工作的(但不是你希望的那样)。它转换为(get db :get-nth-mat n) (3个参数get),如果db中没有键:get-nth-mat,则返回n。
https://stackoverflow.com/questions/59573644
复制相似问题