gpt4 book ai didi

clojure - 让 Clojure 中的 lambda block 扫描器生效

转载 作者:行者123 更新时间:2023-12-02 21:11:05 26 4
gpt4 key购买 nike

我刚刚开始阅读 Let over lambda,我想我应该尝试在闭包章节中编写一个 clojure 版本的 block 扫描器。

到目前为止我有以下内容:

(defn block-scanner [trigger-string]
(let [curr (ref trigger-string) trig trigger-string]
(fn [data]
(doseq [c data]
(if (not (empty? @curr))
(dosync(ref-set curr
(if (= (first @curr) c)
(rest @curr)
trig)))))
(empty? @curr))))
(def sc (block-scanner "jihad"))

我认为这可行,但我想知道我做对了什么以及我可以做得更好。

最佳答案

我不会使用ref-set而是alter,因为您不会将状态重置为全新的值,而是将其更新为获得的新值从旧的开始。

(defn block-scanner
[trigger-string]
(let [curr (ref trigger-string)
trig trigger-string]
(fn [data]
(doseq [c data]
(when (seq @curr)
(dosync
(alter curr
#(if (-> % first (= c))
(rest %)
trig)))))
(empty? @curr))))

那么就没有必要使用 refs,因为您不必协调更改。这里原子更合适,因为它可以在没有所有 STM 仪式的情况下进行更改。

(defn block-scanner
[trigger-string]
(let [curr (atom trigger-string)
trig trigger-string]
(fn [data]
(doseq [c data]
(when (seq @curr)
(swap! curr
#(if (-> % first (= c))
(rest %)
trig))))
(empty? @curr))))

接下来我将摆脱命令式风格。

  • 它的作用超出了应有的范围:它遍历所有数据 - 即使我们已经找到了匹配项。我们应该早点停下来。
  • 它不是线程安全的,因为我们多次访问原子 - 它之间可能会发生变化。所以我们只能接触原子一次。 (虽然在这种情况下这可能并不有趣,但养成习惯是件好事。)
  • 这很丑。当我们得出结果时,我们可以功能性地完成所有工作并保存状态。
(defn block-scanner
[trigger-string]
(let [state (atom trigger-string)
advance (fn [trigger d]
(when trigger
(condp = d
(first trigger) (next trigger)
; This is maybe a bug in the book. The book code
; matches "foojihad", but not "jijihad".
(first trigger-string) (next trigger-string)
trigger-string)))
update (fn [trigger data]
(if-let [data (seq data)]
(when-let [trigger (advance trigger (first data))]
(recur trigger (rest data)))
trigger))]
(fn [data]
(nil? (swap! state update data)))))

关于clojure - 让 Clojure 中的 lambda block 扫描器生效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3306779/

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