Elixir 從 1.12.0 開始,新增了一個function 叫 Kernel.tap/2
,官方的範例是這樣使用
1
2
| iex> tap(1, fn x -> x + 1 end)
1
|
可以看到 1
pipes 進 tap 這個 function 裡面以後,不管 function 裡面做了什麼事情,他都會回傳 1
,也就是當初傳入 tap 時的參數
這個有什麼好處呢?我們有時候在 pipes 的過程中,會需要做一些像是副作用
的效果,但又想要保持傳出去的參數不變,所以有時候會不小心就這樣寫
1
2
3
4
5
6
7
8
9
10
11
12
| def do_something_b(val) do
do_other_thing(val)
# ...
val
end
def do_thing() do
val
|> do_something_a()
|> do_something_b()
|> do_something_c()
end
|
但其實我們可以用 Kernal.tap()
來做到一樣的事情,就如同文章一開始的範例一樣
1
2
3
4
5
6
7
8
9
10
| def do_something_b(val) do
do_other_thing(val)
end
def do_thing() do
val
|> do_something_a()
|> tap(&do_something_b/1)
|> do_something_c()
end
|
看一下 Elixir 原始碼是怎麼做到這件事情
1
2
3
4
5
6
7
| @doc since: "1.12.0"
defmacro tap(value, fun) do
quote bind_quoted: [fun: fun, value: value] do
_ = fun.(value)
value
end
end
|
其實也很單純,就是幫你把傳進來的參數丟給你傳進來的 function 後,再丟出去
疑?!等等,這不是跟原本的 code 很像嗎?其實 Elixir 也只是幫你做掉這件事情,就是這麼簡單暴力😂