2017-03-02 161 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刪除。 –