特殊形式 with 提供了一种方式,让你把注意力放在一串可能失败的步骤的“顺利路径”上,之后再处理这些失败。
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的元组里返回,然后回家。