gpt4 book ai didi

clojure - 在 Clojure 中解构命令的惯用方法

转载 作者:行者123 更新时间:2023-12-02 04:42:09 26 4
gpt4 key购买 nike

这是我使用 clojure.core.match 编写的一些代码,它执行一个非常常见的编程任务。一个函数需要一些“命令”(或“对象”、“记录”,或任何你喜欢调用它们的东西),必须对每种类型做不同的事情,并且必须解构它们以弄清楚要做什么,并且不同命令类型可能必须以不同方式解构:

(defn action->edits [g action]
"Returns vector of edits needed to perform action in graph g."
(match action
[:boost from to]
[[:add-edge from to 1.0]]
[:retract from to]
[[:remove-edge from to]]
[:normalize from to] ; a change has just been made to from->to
(map (fn [that] [:remove-edge from that])
(successors-except g from to))
[:recip-normalize to from] ; a change has just been made to from->to
[]
[:reduce-to-unofficial from to competitor]
[[:remove-edge from to] (make-competitive-edge from competitor]))

我主要是在模仿人们通常使用 pmatch 的方式Scheme 中的宏。我想知道在 Clojure 中执行此操作的惯用方法是什么。

我喜欢上面的代码:

  • 非常可读。

  • 写起来毫不费力。

这是我不喜欢的:

  • match 宏以外的任何地方访问 fromto 字段是极其不可读且容易出错的。例如,要从大多数 Action 向量中提取 from 元素,您可以编写 (action 1)。如果我添加新操作,该代码将会中断,并且它现在在 :recip-normalize 上中断。

  • match 生成的代码效率低下:它通过反复抛出和捕获异常来进行搜索。它不只是生成一个大的嵌套 if

我尝试过将命令表示为 map ,但它似乎变得冗长,而且命令的名称也不太突出,大大降低了可读性:

  (match action
{:action :boost :from from :to to}
[{:edit :add-edge :from from :to to :weight 1.0}]
{:action :retract :from from :to to}
[{:edit :remove-edge :from from :to to}]
. . .)

match 的 future 版本可能会生成更好的代码,但现在生成的糟糕代码(以及缺乏对记录的支持)表明,在 Clojure 中,人们多年来一直在愉快地处理这种事情没有匹配。那么,您是如何在 Clojure 中做这种事情的?

最佳答案

我会利用 clojure 的内置 destructuring facilities ,因为我在这里没有看到对 core.match 的要求 - 但我可能会遗漏一些东西。

例如:

(defn action->edits [g [action from to]]
(condp = action
:boost "boosting"
:retract "retracting"
:normalize-ksp-style (recur g [:boost from to])
nil))

(action->edits 2 [:normalize-ksp-style 1 2])
;=> "boosting"

关于clojure - 在 Clojure 中解构命令的惯用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36506808/

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