これは私の以前の質問のフォローアップです。
Let Over Lambdaを読んで奇妙なオブジェクトスキームを思いついたので、プロトコルに勝る利点は考えられませんが、意見を聞きたいと思います。高階関数とカプセル化の使用を検討しているところです。
(defn new-person
"Construct a new Person object and return a Map of accessor methods."
[init-first-name init-last-name init-age]
(let [first-name (ref init-first-name)
last-name (ref init-last-name)
age (ref init-age)]
{:get-first-name #(@first-name)
:set-first-name #(dosync (ref-set first-name %1))
:get-last-name #(@last-name)
:set-last-name #(dosync (ref-set last-name %1))
:get-age #(@age)
:set-age #(dosync (ref-set age %1))}))
次のようなオブジェクトを使用できます。
(def fred (new-person "fred" "flintstone" 42))
次の方法でアクセサメソッドを取得します。
(fred :get-age)
しかし、アクセサーを呼び出す方法がわかりません。
「インスタンス」変数のすべての変更はSTMで発生するため、作成されたオブジェクトはスレッドセーフです。
更新:新しく改良されたバージョン:
(defn new-person
"Construct a new Person object and return a Map of accessor methods."
[init-first-name init-last-name init-age]
(let [first-name (ref init-first-name)
last-name (ref init-last-name)
age (ref init-age)]
{:first-name
(fn
([] @first-name)
([val] (dosync (ref-set first-name val))))
:last-name
(fn
([] @last-name)
([val] (dosync (ref-set last-name val))))
:age
(fn
([] @age)
([val] (dosync (ref-set age val))))}))