with特殊形式 with 提供了一種方式,讓你專注在一連串可能失敗的步驟的「happy path」上,之後再處理失敗的情況。
with {:ok, id} <- get_id(username),
{:ok, avatar} <- fetch_avatar(id),
{:ok, image_type} <- check_valid_image_type(avatar) do
{:ok, image_type, avatar}
else
:not_found ->
{:error, "invalid username"}
{:error, "not an image"} ->
{:error, "avatar associated to #{username} is not an image"}
err ->
err
end
在每一步,只要子句符合,這個鏈就會繼續下去,直到執行do區塊為止。如果有一步比對失敗,鏈就會停止,並回傳不符合的子句。你也可以選擇使用else區塊來捕捉失敗的比對,並修改回傳值。
你的護照快要過期了,所以你得跑一趟市公所換發新護照。根據過往經驗,你知道市公所不見得是最好打交道的單位,於是你決定盡量「專注在順利路徑上」。
你把換發新護照所需的表格印出來、填好,跳上車、繞過一個街區、停好車,然後往公所走去。
以下所有任務都會需要實作並擴充get_new_passport/3。
結果發現這棟大樓只在下午開放,而且每天開放的時間還不一樣。
用目前時間(作為get_new_passport/3的第一個引數傳給你)呼叫函式enter_building/1。如果大樓有開,這個函式會回傳一個帶有:ok和時間戳記的元組,這個時間戳記你之後會用到;否則會回傳一個帶有:error和訊息的元組。目前,順利路徑可以直接回傳:ok元組。
如果你拿到:error元組,就用else區塊把它回傳。
服務台以喝很久的咖啡休息時間聞名。如果你運氣夠好,遇到有人在的話,對方會給你一本說明手冊,裡面會依照你的出生日期,告訴你該去哪个櫃檯。
用目前時間呼叫函式find_counter_information/1。你會拿到一個帶有:ok和一本手冊(以匿名函式表示)的元組,或是帶有:coffee_break和更多指示的元組。在你的順利路徑中,也就是拿到手冊的情況,把這本手冊套用到你的生日(get_new_passport/3的第二個引數)上。它會回傳你該去的櫃檯號碼。回傳一個帶有那個櫃檯號碼的:ok元組。
如果你拿到:coffee_break訊息,就回傳一個帶有:retry和一個指向目前時間 15 分鐘後的NaiveDateTime的元組。和之前一樣,如果你拿到:error元組,就把它回傳。
不知為何,不同的櫃檯要求不同顏色的表格。當然,你印的是你在網站上找到的第一份,所以你專注在自己的順利路徑上,並祈求一切順利。
用你在入口拿到的時間戳記、櫃檯,以及你帶來的表格(get_new_passport/3的最後一個引數)呼叫函式stamp_form/3。你會拿到一個帶有:ok和校驗碼(用來驗證你的護照號碼)的元組,或是一個帶有:error和訊息的元組。讓你的順利路徑回傳一個帶有校驗碼的:ok元組。如果你拿到:error元組,就把它回傳。
終於,你需要的文件都齊全了。
用先前拿到的時間戳記、櫃檯和校驗碼呼叫get_new_passport_number/3。你會收到一個字串,內容是你最終的護照號碼,剩下要做的就是把它放進一個帶有:ok的元組回傳,然後回家。