参照渡し

2021-03-08

ruby

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

tap はselfへの参照をブロック引数に渡しつつselfを返すので |hash|{} への参照
hash = hash.merge({ foo: 'FOO' }) は その参照(hash)に hash.merge({ foo: 'FOO' }) の結果を再代入
{} を参照しなくなるのでこの時点で hash{} は完全に別物。hashはただのローカル変数

{} の状態を変更したければ参照した実体を操作する必要がある(merge! とか []= とか shiftとか)

eachやmapも同じなのになんでこんな勘違いしたんだろう。不思議

コメント

投稿する

投稿したコメントはご自身で削除できません

不適切なコメントと判断した場合は管理側で削除することがあります