【问题标题】:Clojure STM simple programClojure STM简单程序
【发布时间】:2018-12-04 18:26:03
【问题描述】:

我正在编写一个简单的程序来使用 Clojure 的 STM 转换两个整数的值。 我正在关注 Lewandowski (http://lewandowski.io/2016/01/clojure-summary/) 的方法,使用他的函数 a06。

我的代码:

(defn trans [p1 p2]
  (println "a")
    (dosync
      (let [newval1 (@p1 + 50)
            newval2 (@p2 - 30)]
        (do 
          (println "b")
          (ref-set p1 newval1)
          (ref-set p2 newval2)))))

(defn main []
   (let [p1 (ref 20) p2 (ref 100)]
     (do
       (future (trans p1 p2))
       (future (trans p1 p2))
       (Thread/sleep 500))    
   (println @p1)
   (println @p2))) 

由于某种原因,我的 main 函数没有进入函数 trans 的“执行部分”。因此,我的输出只有:

a
a
20
100
=> nil

我添加了“a”和“b”来显示我的问题。 如果这是我犯的一个非常简单的错误,我很抱歉,但我根本看不到我的代码中缺少什么。每个答案都非常感谢!谢谢!

【问题讨论】:

  • 顺便说一句,请注意(@p1 + 50) 是中缀,需要更正为(+ @p1 50)
  • @CharlesDuffy 我认为这不是真的。未来由线程池中的条目支持。您丢失了对可让您查看结果的对象的引用,但线程池仍然具有对其任务的引用。您的版本正确成功,因为您修复了中缀数学 - 它曾经在产生任何副作用之前引发异常。
  • 我认为线程池条目被弱引用,但很可能完全考虑了不同的运行时/构造。

标签: clojure stm


【解决方案1】:

比较以下,正确工作:

(defn trans [p1 p2]
  (println "a")
  (dosync
   (let [newval1 (+ @p1 50)
         newval2 (- @p2 30)]
     (do
       (println "b")
       (ref-set p1 newval1)
       (ref-set p2 newval2)))))

(defn main []
  (let [p1 (ref 20) p2 (ref 100)]
    (let [f1 (future (trans p1 p2))
          f2 (future (trans p1 p2))]
      (Thread/sleep 500))
    (println (pr-str @p1))
    (println (pr-str @p2))))

也就是说,当您的兴趣在于副作用时,期货并不是真正的理想工具,而不是稍后检索计算结果本身。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-11
    • 2011-04-04
    • 1970-01-01
    相关资源
    最近更新 更多