rubyの破壊するとかしないの話
はじめに
rubyを初めて書いてみて破壊するしないみたいな話題が出てきた際、いまいち想像できなかったので、ちょっと調べてみました。
調べていくうちに次第に興味がわいてきたので、一通り試したり調査して理解したことをまとめました。
全五回に分割してありますが、短くまとめてあるので、是非とも通して読んでいただきたいなと思います。
ruby 破壊の話シリーズ |
---|
ruby 破壊の話①「=」のふるまい |
ruby 破壊の話②メソッド編 |
ruby 破壊の話③関数編 |
ruby 破壊の話④破壊的なメソッド編 |
ruby 破壊の話⑤dup編 |
全部読むと
- 破壊とはどのように行われるか
- =と破壊的メソッドの違い
- 完全な複製の作り方
などが理解できると思います。
環境
$ ruby -v
ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux-gnu]
$ irb
irb(main):001:0>
"="
これをこれまで代入と呼んでいたけど、rubyだと代入とは違う気もする。
一番近いのは「エイリアス」かなと。
ちなみに"=="や”===”は全く関係ない。あくまで"="のふるまいの話をする。
突き詰めると"="のふるまいを理解してからrubyがかなり好きになったと思う。
rubyの=は代入ではない(と思う)。
これが他の言語と違っていて、最初は戸惑ったけど慣れるとむしろすごく良いシステムだった。
rubyの=は「左辺は右辺のオブジェクトを参照してね」という命令と理解している。idの代入じゃないかと言われるとまあ確かに代入かもしれない・・・
一回だけ使う場合
まずはわかりやすいmutableの例から。
mutableとかimutableの話はまた別の記事で書きます。
mutableの例
irb(main):001:0> a='aaa' #変数aが文字列aaaを指すように設定(文字列aaaはこの世界にたくさん存在する)
=> "aaa"
irb(main):002:0> a.__id__ #変数aのobject_id
=> 47197188120260
irb(main):003:0> a.__id__ #変数aはこの世界に一つしか存在しないので、何度確認しても変わらない
=> 47197188120260
irb(main):004:0> 'aaa'.__id__ #文字列aaaのobject_id
=> 47197187994020
irb(main):005:0> 'aaa'.__id__ #同じ文字列でも評価のたびに異なるobjectであることが
=> 47197187807940
irb(main):006:0> 'aaa'.__id__ #object_idを確認すればわかる
=> 47197187768200
irb(main):007:0> 'aaa'.__id__=='aaa'.__id__ #評価のたびに異なるからfalse
=> false
irb(main):008:0> a.__id__=='aaa'.__id__ #参照してねという命令であり、この'aaa'はさっき(001)の'aaa'とは異なるのでfalce
=> false
immutableの例
muttableとだいぶ異なることがわかる
irb(main):001:0> a=:aaa #変数aがシンボルaaaを指すように設定(シンボルaaaはこの世界に一つしか存在しない)
=> "aaa"
irb(main):002:0> a.__id__ #変数aのobject_id
=> 1162268
irb(main):003:0> a.__id__ #変数aはこの世界に一つしか存在しないので、何度確認しても変わらない
=> 1162268
irb(main):004:0> :aaa.__id__ #シンボルaaaのobject_idはaに割り当てられたidと同じ
=> 1162268
irb(main):005:0> :aaa.__id__ #同じシンボルなら常に同じidであることが
=> 1162268
irb(main):006:0> :aaa.__id__ #object_idを確認すればわかる
=> 1162268
irb(main):007:0> a.__id__==:aaa.__id__ #世界に一つの変数aとシンボルaaaの参照先を001でそろえたので
=> true
irb(main):008:0> a.__id__===:aaa.__id__ #これら二つはどこまでも同じ
=> true
複数回使う場合
mutableの例
irb(main):001:0> a='abc' #変数aが文字列abcを指すように設定
=> "abc"
irb(main):002:0> a.__id__ #変数aのid
=> 46923898737600
irb(main):003:0> a="abc" #一見意味のないコード
=> "abc"
irb(main):004:0> a.__id__ # 003で新たな参照先に変わったのでidも変わる
=> 46923898698140
irb(main):005:0> a="cba" # もちろん異なる文字列に設定すると
=> "cba"
irb(main):006:0> a.__id__ #idも変わる
=> 46923898682240
irb(main):007:0> a=a #左辺aの参照先を右辺aの参照先に設定する
=> "cba"
irb(main):008:0> a.__id__ #右辺aの参照先は006の値だから設定しなおしても変わらない
=> 46923898682240
irb(main):009:0> a=a+"x" #左辺aの参照先を右辺aにxをつなげたオブジェクトに設定する
=> "cbax"
irb(main):010:0> a.__id__ #右辺aにxをつなげたオブジェクトはaとは異なるオブジェクトなのでidも異なる
=> 46923898381420
immutableの例
こちらもかなり異なる
irb(main):001:0> a=:abc #変数aがシンボルabcを指すように設定
=> :abc
irb(main):002:0> a.__id__ #変数aのid
=> 1162268
irb(main):003:0> :abc.__id__ #シンボルabcのidと一致する
=> 1162268
irb(main):004:0> a=:abc #一見意味のないコード
=> :abc
irb(main):005:0> a.__id__ #immutableの場合は本当に意味が無い
=> 1162268
irb(main):006:0> a=:cba #aの参照先をシンボルcbaに変更
=> :cba
irb(main):007:0> a.__id__ #参照先が変わったのでidも変更
=> 1162588
irb(main):008:0> :cba.__id__ #参照先はシンボルcbaと一致
=> 1162588
ざっくり"="は参照先idを更新する命令だという理解で良いと思う。
逆に=が無ければidは変わらないし、値も変わらない。。。
わけではない。
実は=なしで値は変えられる。
続きは次の記事で。
まとめ
rubyにおける「=」の働きは、object_idを上書きすることである。