【问题标题】:clojure bank account money transfer exampleclojure 银行账户汇款示例
【发布时间】:2017-03-02 20:39:03
【问题描述】:

我是 clojure 的新手,我正在尝试实现经典的并发示例,即 bank account transfer。我想使用transactional memory 来实现它。

这是java中的一个例子

static class Account {
    private double balance;

    public synchronized void withdraw(double value) {
        balance -= value;
    }

    public synchronized void deposit(double value) {
        balance += value;
    }
}

static synchronized void transfer(Account from, Account to, double amount) {
    from.withdraw(amount);
    to.deposit(amount);
}

在我的实现中不确定,但它似乎有效。

这是我在clojure中的代码

(deftype Account [balance])

(def account1 (Account. (ref 100)))
(def account2 (Account. (ref 100)))

(defn print-accs []
    (println " account 1 => " (deref (.balance account1))
             " account 2 => " (deref (.balance account2))))

(defn transfer [from to amount]
    (dosync
        (alter (.balance from) - amount)
        (alter (.balance to) + amount)))

(print-accs) ; 100 100

(transfer account1 account2 10)

(print-accs) ; 90 110

是使用transactional memory 或正确实现bank account transfer 的正确示例吗?我是否对字段使用了正确的ref,还是应该对整个Account 实例使用它?

【问题讨论】:

  • transfer 中的错字?你传入from to,但稍后使用account[12]
  • 确实如此。固定

标签: java clojure stm


【解决方案1】:

你不需要deftype,否则它看起来不错。我会像这样简化一点:

(def account1 (ref 100))
(def account2 (ref 100))

(defn print-accs []
    (println " account 1 => " @account1
             " account 2 => " @account2 ))

(defn transfer [from to amount]
    (dosync
        (alter account1 - amount)
        (alter account2 + amount)))

(print-accs) ; 100 100

(transfer account1 account2 10)

(print-accs) ; 90 110

我推荐的一件事是review The Clojure Cheatsheet 并始终保持浏览器选项卡对其打开。这些链接指向 ClojureDocs.org 上的更详细信息,such as that for dosync。尽情享受吧!

更新

对于像帐户余额这样的单个值,将余额包含在 Account 记录中没有多大意义。如果您想创建一组具有相同字段的记录,您可能需要defrecord

(defrecord Account [name balance])

大多数应用一开始都使用像

这样的普通地图
(def joe-acct (ref {:name "Joe" :balance 100.00})

因为它简单灵活。稍后,如果您想为始终包含名称和余额的地图提供类型名称,您可以切换到

(defrecord Account [name balance])
(def joe-acct (ref (Account. "Joe" 100.00))) 

deftype 被认为是“低级”,现在很少使用。见:

【讨论】:

  • 好吧,我使用了deftype,因为我想模仿为Account 创建一个特定的类。这就是为什么我问我是否应该将Ref 存储为其Accountbalance 字段实例,因为我不确定。
  • 顺便说一句,您是否偶然知道Refs 何时从内存中删除?通过 GC?
  • 一个 ref 和其他的一样是一个“对象”,当不再被引用时它会被 GC 删除。
  • 那么帐户实例的ref 呢?我将ref 设置为值-如果我将Account 包装成ref 像这样(def ref-acc (ref (Account. 100))) 会有区别吗?
  • 但是如果我有多个字段 - 我应该使用什么方法?整个班级还是只是字段?
猜你喜欢
  • 2011-04-27
  • 2020-08-22
  • 2015-12-10
  • 1970-01-01
  • 1970-01-01
  • 2011-11-20
  • 1970-01-01
  • 2018-11-01
  • 2016-11-25
相关资源
最近更新 更多