Rubyをメインに勉強中の初学者です。
自分用のアウトプット記事になります。Qiitaの書き方もあまりわかってません(;ω;)
間違ってる箇所が多数あるかもしれませんが何卒ご了承ください。
"りんご".equal?("りんご")
# => false
これですよ!
a = "りんご"
b = "りんご"
#equal?は2つのオブジェクトが同じかを確認するメソッドだよ〜。
a.equal?(b)
#=> false
これなんですよ。
”りんご”と”りんご”が違うと言ってくるRubyの世界のお話ですよ。
生だと「リンゴ」、加工されてると「りんご」って言うらしいからこの2つは違うよ〜^ ^
とか、そういう次元じゃないんですよ。
”りんご”と”りんご”が違うんですよ。
同じなわけねぇだろと言ってくるわけです。
これってあれですか?
「人間はみんな違うんだよ、とかいつも人間に対してばかり綺麗事ほざきやがって…りんごだってなぁ、一つとして同じものはねぇんだよ」
みたいな青森農家おじさんの悲痛の叫びとかそういうことですか?
今回はこの”りんご”と”りんご”が違う件について、真剣に考えよう、真剣に考えて青森のおじさんを説得しようの回でございます。
※ 本記事ではこの先、真剣に考えている箇所が1つもございません。
下記の内容について、もはや遠回りと言えよう、訳の分からぬ例え話を用いて考えてみたのが本記事となっております。
a = "りんご"
で"りんご"
っていう文字列オブジェクトを参照するよ- 同じく変数
b
でも"りんご"
っていう文字列オブジェクトを参照するよ。- 文字列オブジェクトは、同じ名前でも登場するたびに新しいオブジェクトとして作成される性質があるよ。
- つまり
a
とb
が参照する”りんご”は名前が同じだけど中身が違うね。⇒a.equal?(b)はfalseになるよ。
お暇な方がいらっしゃいましたらぜひ覗いていただけると幸いです!!
そもそもa = "りんご"
はなんなのか。
a = "りんご"
って、何を表しているコードですか?
- 変数aに文字列”りんご”を代入する」
- 「左オペランドの変数aと右オペランドの文字列”りんご”を紐づける」
- 変数aは文字列”りんご”への参照を保持する
とか色々表現できそうですね。じゃあ参照を保持ってなんなん…。
変数は実体そのものじゃなくて、実体がどこにあるかっていう場所のデータを格納するんだなんちゃらかんちゃら…。
色々とたまにこんがらがりませんか。
変数を「人」、文字列を「商品」として考えてみる
もうこれ変数⇒人、文字列⇒商品って言い換えてみて
「人aに商品"りんご"を指差してもらう」
って考えるとイメージしやすいかもと思ったわけです。
例えばスーパーマーケットで指を差してもらうんです。
a =
って言われたら何か絶対に指ささないといけないんです。
a = “りんご”
って言われたらりんごを指せばいいんです。
# aさん、どれかひとつりんごを指さしてね!
a = "りんご"
というよりrubyの世界においては人の本質は「何かに指をさす」ことなんです(そんなわけない)。もはや何かを指差してる状態じゃないと人として認められないんですよ(そんなことあって良いわけがない)。
a = "りんご"
でりんごを指差すことで初めて、aさんは人として存在することになるんですね。
bさんにも同じ指示を出しましょうか。b =
って言われたら絶対に何か指差さないといけないんです。でもスーパーには同じ商品が何個もありますよね。
なので、わざわざこのときにbさんが指すのはaさんと同じりんごじゃなくていいんですよ。
# bさんもどれかひとつりんごを指さしてね!
b = "りんご"
さて、このときaさんとbさんが指差している”りんご”は同じなのか?を確認するのがequal?
でしたね!
# aさんとbさんが指さしてるりんごは同じ?違うね。
a.equal?(b) #=> false
そうです、false
になってしまうのは、「りんご」ではあるんだけれど、違うりんごを指差しているからなんですね!!
実際にaさんとbさんが指しているこの2つの"りんご"のオブジェクトIDも確認してみましょう。object_id
で確認できますどうでしょうか。違う番号の"りんご"を指差しているのが確認できますね。
a.object_id #=> 94360
b.object_id #=> 105580
人に指を差してはいけない
じゃあよく見るa = b
みたいな変数に変数を代入してるのはなんなのでしょうか。
同じ考え方でいくと、「aさんにbさんを指差してもらう」ですね。
でもどうですか?bさんは人ですよね。人に対して指差すのは失礼に当たります。
しかし、命令をもらったからには何かを指差すほかありません。
さあどうしましょうか…おや?
bさんを確認してみるとどうやら「105580番のりんご」を指していますね。
この場合は、「aさんはbさんの真似をする」とイメージするとわかりやすいかも。つまりbさんのりんごと全く同じものを指差せば良さそうですね!!
# 今、aさんとbさんは違うりんごを指差している状態。
# やっぱりaさん!!bさんと同じ"りんご"を指さして!!
a = b
本当に同じ"りんご"を指しているのでしょうか。equal?
で確認してみると…true
になりますね!!
a.equal?(b)
=> true
オブジェクトIDを確認してみてもbさんが指していた105580番の”apple”をaさんも指していることがわかりますね。
a.object_id #=> 105580
b.object_id #=> 105580
定義されていない人
ではここから新キャラ、cさんを登場させてみましょう。
a = c #undefined local variable or method `c' for main
まず、a = c
。これはダメみたいですね。なぜでしょうか。
指差し論で考えると、「aさんにcさんを指差してもらう」ですね。
でも果たしてこの段階でcさんは存在しているのでしょうか。
先ほど
人の本質は「何かに指を指す」こと。もはや何かを指している状態じゃないと人として認められない
とお話ししました。
そうですね、cさんはまだ何に対しても指を差していない状態なんです。つまりこの世界においては存在として認められていません。その段階で「cさんを指差して!!」って言っても、aさんからしたら「誰それ?おらんねんけど」となってしまうということですね。
ではc = a
はどうですか?
c = a #=> "apple"
c.object_id #=> 105580
ちゃんと通りましたね。object_idで確認してみても、aさんが指差してるのと同じものなのが分かります。
先ほどと違うのは「cさんにaさんを指差してもらう」というところ。cさんに対して命令を出しています。このときのcさんの動きを確認してみると…
- aさんを指差すように命令される。
- aさんは人だから、指差してはいけない。だからaさんの真似をする。
- aさんと同じりんごを指差す
という流れになってるんですね。cさんが人として認められる段階として必要な指示だから、エラーが起きていないという感じですね。
シンボルはスーパーの値札と考えよう。
最後にもうひとつ。文字列じゃなくてシンボルで考えてみましょう。
# aとbにシンボル:りんごを代入
a = :りんご
b = :りんご
# aとbは同じオブジェクトを参照してる?
a.equal?(b)
=> true
文字列とは打って変わって、同じシンボルですよ。ってなりましたね。なぜでしょうか。
シンボルは「スーパーの値札」だと考えてましょう。値札は1つの商品に1つですよね。
a = :りんご
「aさん、りんごの値札を指差して!!」
b = :りんご
「bさん、りんごの値札を指差して!!」
という指示になるわけですが、当然、同じ商品の値札というのは一つなので、同じ値札を指差すことになります。
シンボルは文字列と違い、「内容が同じであればどこでも同じものが使い回せる」という性質を持っているようですね。
締め締め
ということで、
「変数に値を代入する」がよくわからなくなった時は、
「人(変数)にモノ(オブジェクト)を指差してもらう」っていう考え方で捉えてみるのもたまには良いのではななかろうか!!
というお話でした。
ここまで読んでくださった方、もしいらっしゃいましたら本当にありがとうございます(><)
本日まとめはこちら(´꒳`)
- 文字列は同じ内容でも登場するたび新しく作成されるよ
- シンボルは同じ内容だと必ず同じオブジェクトになるよ
- 青森農家のおじさんは間違ってないかも、かも!!
ほなまた!!