gpt4 book ai didi

clojure - 处理 map 中打包的数据结构的惯用方法?

转载 作者:行者123 更新时间:2023-12-01 12:43:06 30 4
gpt4 key购买 nike

假设我们有一个描述移动球的数据结构。

(def moving-ball {:position [100 100]
:velocity [1 3]
:acceleration [0 0]})

编写一个 update-fn 来解构 map 、更新属性并返回一个新 map 是否符合习惯?像那样:

(defn update-acceleration
[{:keys [position] :as s} mx my]
(let
[[x y] position
dx (- mx x)
dy (- my y)
dir (normalize [dx dy])]
(assoc s :acceleration dir)))

还是把功能分开比较好?

(defn direction
[[x y] mx my]
(let [dx (- mx x)
dy (- my y)]
(normalize [dx dy])))


(defn update-map
[{:keys [position] :as s} mx my]
(assoc s :acceleration (direction position mx my)))

第一个与数据结构耦合(因此不是真正可重用的),但第二个需要更多代码。有更好的方法吗?

最佳答案

如果我们改进数据呈现给函数的方式,我们可以有效地从与 map 数据结构的纠缠中提取函数方向。这与重构人员所说的 introduce (or extract) parameter object 有关。和 extract method .

问题是 [x y] 坐标的呈现方式不均匀:有时是两个数字,有时是一对。如果我们将它们全部表示成对,我们可以更好地掌握函数的作用。

如果我们对 direction 函数执行此操作,它将变为 ...

(defn direction [[x y] [mx my]]
(let [dx (- mx x)
dy (- my y)]
(normalize [dx dy])))

...我们可以将其简化为...

(defn direction [from to] (normalize (mapv - to from)))

现在我们有了一个一眼就能看懂的函数。由于它很可能会在 update-acceleration 之外以及在其中找到用途,因此它是可行的。 (具有无意义参数名称的相同函数并不那么令人信服)。

本着同样的精神,我们可以改造update-acceleration:

(defn update-acceleration [{:keys [position] :as s} [mx my]]
(let
[[x y] position
dx (- mx x)
dy (- my y)
dir (normalize [dx dy])]
(assoc s :acceleration dir)))

...减少为...

(defn update-acceleration [s m]
(assoc s :acceleration (normalize (mapv - m (:position s)))))

... 或者,使用 direction 函数,...

(defn update-acceleration [s m]
(assoc s :acceleration (direction (:position s) m)))

您可以从任何语言的重构中获益。 Clojure 的序列库放大了这种效果。 (其他序列库可用:任何 Lisp 或其他函数式语言、Smalltalk、C#、... YMMV)


附言

我猜测 normalize 会返回一个相同方向的单位向量。这是使用序列函数执行此操作的一种方法:

(defn normalize [v]
(let [length (->> v
(map #(* % %))
(reduce +)
Math/sqrt)]
(mapv #(/ % length) v)))

这绝对值得提取。事实上,我很想拉出 length:

(defn length [v]
(->> v
(map #(* % %))
(reduce +)
Math/sqrt))

... 并将 normalize 定义为 ...

(defn normalize [v]
(let [l (length v)] (mapv #(/ % l) v)))

一个小小的警告:mapv 将在其最短的参数处静默停止,因此您可能需要检查其所有参数的长度是否相同。

关于clojure - 处理 map 中打包的数据结构的惯用方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22514320/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com