Ral*_*lph 2 encapsulation clojure higher-order-functions
这是我之前的问题的后续行动.
我在阅读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))}))
Run Code Online (Sandbox Code Playgroud)
我可以使用这样的对象:
(def fred (new-person "fred" "flintstone" 42))
Run Code Online (Sandbox Code Playgroud)
并以这种方式检索访问器方法:
(fred :get-age)
Run Code Online (Sandbox Code Playgroud)
但我无法弄清楚如何调用访问器.
创建的对象是线程安全的,因为"实例"变量的所有变异都发生在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))))}))
Run Code Online (Sandbox Code Playgroud)
也许不是你的问题的100%答案,但你会尝试做的不是Clojure非常惯用."标准"解决方案如下:
(defrecord Person [first-name last-name age])
(def fred (Person. "fred" "flintstone" 42))
(fred :age)
Run Code Online (Sandbox Code Playgroud)
看起来你强迫OO可变状态进入Clojure'对象'