1
2
3
> a = {}.tap {|hash| hash = hash.merge({ foo: 'FOO' }) }
> a
=> {}
会社の同僚に上のようなコードを見せられて「なんでだと思います?😢」って相談されて
「ウーンウーン」と一緒になって悩んでしまったのでメモしとく
ちなみに条件次第でhashに新しい要素を追加したりしたいらしい
やりようは色々あると思うけど
1
2
> a = {}.tap {|hash| hash.merge!({ foo: 'FOO' }) }
=> {:foo=>"FOO"}
とか
1
2
3
> hash = {}
> b = hash.tap { hash = hash.merge({ foo: 'FOO' }) }
=> {:foo=>"FOO"}
とか
シンボリックリンクみたいなイメージと解釈している
シンボリックリンクを呼べばリンク先のファイルを開いたり実行したりできるけど、rm したり cp で同名のファイルを上書きしたりしてもリンク先のファイルには影響しない。
そんな感じ
納得できなければるびまで解説してくれてるのでそっち読もう
tap
はselfへの参照をブロック引数に渡しつつselfを返すので |hash|
は {}
への参照
hash = hash.merge({ foo: 'FOO' })
は その参照(hash)に hash.merge({ foo: 'FOO' })
の結果を再代入
{}
を参照しなくなるのでこの時点で hash
と {}
は完全に別物。hashはただのローカル変数
{}
の状態を変更したければ参照した実体を操作する必要がある(merge! とか []= とか shiftとか)
eachやmapも同じなのになんでこんな勘違いしたんだろう。不思議
コメント