首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在cljs re中创建自定义的getter查询?

如何在cljs re中创建自定义的getter查询?
EN

Stack Overflow用户
提问于 2020-01-03 13:33:21
回答 1查看 47关注 0票数 1

我正在写一个重帧应用程序,它模拟了一个棋盘游戏,其中我有一个包含单元数组的棋盘结构,类似于:

代码语言:javascript
复制
{... :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.cljsreg-sub上做这件事,但它似乎不起作用。是的,我可以创建自己的getter:

代码语言:javascript
复制
(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)方便或友好

非常感谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-01-03 17:28:11

db只是一个地图,这个“特征”与重帧无关,但每个地图都是一个函数,关键字也是一个函数。所以当你使用(map something)(:keyword something)时,你实际上是在使用(get map something)(get something :keyword)

因此,除了以不同的方式访问/迭代您的数据(例如doseqformap等)之外,真的没有什么“捷径”--假设您要逐个单元格地渲染网格;这样您就完全摆脱了基于索引的访问。

否则,我会使用像您这样的专用函数,但更愿意将其命名为material-by-idx (在OO中,将函数命名为getset类似访问器是相当不常见的(但也有它的位置,例如,设置状态修改))。

正确命名,理想情况下是纯函数,正确地做一件事是函数式和Lisp编程中一个重要的构建块。通常,必须键入更多内容的缺点可以通过更高级的编程范例来缓解,比如线程或部分应用程序,或者作为最后的手段,宏。

您可以使用get-in将其整理一下:

代码语言:javascript
复制
(defn material-by-idx [db idx]
  (get-in db [:board-cells idx :material]))

例如,你现在可以在你的循环中使用类似这样的东西,如果你在其中看到了价值:

代码语言:javascript
复制
(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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59573644

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档