2017-03-02 159 views
0

我是clojure的新手,我正在尝试实施经典并发示例,即bank account transfer。我想用transactional memory来实现它。clojure银行帐户汇款示例

这里是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实例?

+0

错字?你传入'from to',但后来使用'account [12]' – cfrick

+0

哦。固定 – lapots

回答

3

您不需要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被认为是“低级别”,很少采用时下。请参阅:在`transfer`

+0

嗯,我使用了'deftype',因为我想模仿为'Account'创建一个特定的类。这就是为什么我问这个问题,我是否应该为'balance'字段的'Account'实例存储'Ref',因为我不确定。 – lapots

+0

顺便说一句,你有机会知道'Refs'从内存中删除吗?通过GC? – lapots

+1

参考文献与任何其他文献一样是“对象”,它在不再被引用时被GC删除。 –