Agent 模組提供了一層抽象,用來建立行程與 receive-send 迴圈。接下來,我們把透過 Agent 模組啟動的行程稱為 「agent 行程」。我們可以選擇用一個 agent 行程 來代表集中共享的狀態。
要啟動一個 agent 行程,Agent 提供了 start/2 函式。呼叫 start 啟動 agent 行程 時所傳入的函式,會回傳該行程的初始狀態:
# Start an agent process with an initial value of an empty list
{:ok, agent_pid} = Agent.start(fn -> [] end)
就像 Map 或 List 一樣,Agent 也提供了許多處理 agent 行程 的函式。
依照慣例,我們會把與 Agent 相關的所有功能整理並封裝到一個模組裡,用來表示所建模的領域。
你的社區協會請你實作一個簡單的登記應用程式,用來管理社區花園的登記作業。我們已經為你提供了Plot結構。
實作CommunityGarden.start/1函式,它會接收一個選用的選項關鍵字清單,並將這些選項傳遞給 agent 行程。花園的初始狀態應初始化為代表一個空的花圃集合。它應回傳一個帶有花園 pid 的:ok元組。
{:ok, pid} = CommunityGarden.start()
# => {:ok, #PID<0.112.0>}
實作CommunityGarden.list_registrations/1函式。它會接收社區花園的pid。它應回傳一份清單,列出已登記的花圃。
CommunityGarden.list_registrations(pid)
# => []
到目前為止,我們還沒加入登記花圃的功能,所以這個清單應該是空的
實作CommunityGarden.register/2函式。它會接收社區花園的pid以及要登記花圃的名字。成功時,它應回傳帶有花圃 id 與登記對象的Plot結構。
這些 id 應遞增且唯一。你可以在 agent 的狀態中保留一個 id 計數器。
CommunityGarden.register(pid, "Emma Balan")
# => %Plot{plot_id: 1, registered_to: "Emma Balan"}
CommunityGarden.list_registrations(pid)
# => [%Plot{plot_id: 1, registered_to: "Emma Balan"}]
實作CommunityGarden.release/2函式。它會接收要釋出花圃的pid與id。成功時它應回傳:ok。花圃釋出後,該 id 不會被重複使用,只會用來當作唯一識別碼。
CommunityGarden.release(pid, 1)
# => :ok
CommunityGarden.list_registrations(pid)
# => []
實作CommunityGarden.get_registration/2函式。它會接收要檢查花圃的pid與id。如果該花圃已登記,它應回傳該花圃;若未登記,則回傳:not_found。
CommunityGarden.get_registration(pid, 1)
# => %Plot{plot_id: 1, registered_to: "Emma Balan"}
CommunityGarden.get_registration(pid, 7)
# => {:not_found, "plot is unregistered"}