この種のものを JavaScript の例のように動作させたい場合 (つまり、実際の子で実際のアドレス帳を直接検索できるようにする場合)、アドレス帳を変更可能にする必要があります。親と子が最初に作成されたからでもありません (一部の関数型言語では、他の言語よりも簡単に管理できます)。その後、アドレス帳への参照をさらに追加すると、古いエントリが削除されます。古いバージョンのアドレス帳をまだ保持しています。
Clojure では、このような場合にアドレス帳全体を保持するために Atom または Ref を使用してから、各子のアドレス帳を指す Atom または Ref を配置したくなるかもしれませんが、Clojure の参照型は実際には不変データを保持するように設計されているだけです。それらをネストすると問題が発生する可能性があります。
より良い解決策は、エンティティに記号名 (キーワード、数字、UUID はすべて問題ありません) を付けて、マップのどこかに保存することです。単一のアトムを使用すると、次のようになります。
(def state (atom {:contacts {:dirk ...}
:address-books {}}))
次に、次のように Dirk を新しいアドレス帳に追加できます (途中でハッシュ マップの形式で作成します)。
(swap! state (fn [state-map]
(update-in state-map [:address-book :my-address-book]
(fn [abook]
(let [entries (get abook :entries [])]
(assoc abook :entries (conj entries :dirk)))))))
これにより、Dirk がシンボリック参照 ( ) の形式でアドレス帳に追加され、キー:dirk
の下のトップレベルの状態マップで検索されることに注意してください。:contacts
Dirk の連絡先に、それがメンバーであるアドレス帳のリストを維持することも必要な場合はupdate-in
、適切な情報を Dirk の連絡先に追加して、次のようにネストを削除することもでき->
ます。
(-> state-map
(update-in [...] ...)
(update-in [...] ...))