如何在 cljs re-frame 中创建自定义 "getter" 查询?
How to create a custom "getter" query in cljs re-frame?
我正在编写一个重新构建的应用程序来模拟棋盘游戏,其中我有一个包含单元格数组的棋盘结构,例如:
{... :board-cells [{:name "cell-1" :material #object} {:name "cell-2" :material #object} ...]}
虽然 re-frame 支持使用像 (db :board-cells)
这样的关键字语法获取 "natural" 子结构,但我已经厌倦了每次都必须编写整个 "drill-down" 查询我想得到一个 material: (get (nth (db :board-cells) index) :material)
。这也有将我的数据库的物理布局与我的应用程序逻辑紧密耦合的缺点。如果我决定更改我的数据库结构怎么办?然后我必须更新十个不同的点而不是一个。
是否有重新构造官方方法来创建 "virtual query" 以便我可以得到 material 类似 (db :get-nth-mat n)
,其中 n 是 [= 中的单元格编号16=]数组?我认为 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)
方便或好听
非常感谢。
db
只是一张地图和这个"feature"没有关系
重新构建,但每个映射都是一个函数,关键字也是。所以当你
做 (map something)
或 (:keyword something)
你实际上在做什么
(get map something)
和 (get something :keyword)
.
所以真的没有 "shortcut" 除了 accessing/iterating 你的
数据不同(例如 doseq
、for
、map
、...)——假设你是
即将逐个单元地渲染网格;这样你就摆脱了
完全基于索引的访问。
否则我会使用像你这样的专用函数,但宁愿命名
它 material-by-idx
(将函数命名为 get
和
set
类似于 OO 中的访问器(但也有适合它的地方,例如
设置状态修改)).
具有正确命名的、理想情况下纯粹的函数,它只做一件事
properly 是函数式和 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 argument get
),如果没有 key 就 returns 你 n
:get-nth-mat
在 db
.
我正在编写一个重新构建的应用程序来模拟棋盘游戏,其中我有一个包含单元格数组的棋盘结构,例如:
{... :board-cells [{:name "cell-1" :material #object} {:name "cell-2" :material #object} ...]}
虽然 re-frame 支持使用像 (db :board-cells)
这样的关键字语法获取 "natural" 子结构,但我已经厌倦了每次都必须编写整个 "drill-down" 查询我想得到一个 material: (get (nth (db :board-cells) index) :material)
。这也有将我的数据库的物理布局与我的应用程序逻辑紧密耦合的缺点。如果我决定更改我的数据库结构怎么办?然后我必须更新十个不同的点而不是一个。
是否有重新构造官方方法来创建 "virtual query" 以便我可以得到 material 类似 (db :get-nth-mat n)
,其中 n 是 [= 中的单元格编号16=]数组?我认为 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)
非常感谢。
db
只是一张地图和这个"feature"没有关系
重新构建,但每个映射都是一个函数,关键字也是。所以当你
做 (map something)
或 (:keyword something)
你实际上在做什么
(get map something)
和 (get something :keyword)
.
所以真的没有 "shortcut" 除了 accessing/iterating 你的
数据不同(例如 doseq
、for
、map
、...)——假设你是
即将逐个单元地渲染网格;这样你就摆脱了
完全基于索引的访问。
否则我会使用像你这样的专用函数,但宁愿命名
它 material-by-idx
(将函数命名为 get
和
set
类似于 OO 中的访问器(但也有适合它的地方,例如
设置状态修改)).
具有正确命名的、理想情况下纯粹的函数,它只做一件事 properly 是函数式和 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 argument get
),如果没有 key 就 returns 你 n
:get-nth-mat
在 db
.