はじめに
私は現在 Rails を使ったWEBアプリケーションの開発に携わっていますが、ずっと Rails を使っていたわけではありません。以前は PHP や ASP.net を使ってました。
そんな私が Rails での開発を行うようになり、当然言語は Ruby を使うわけですが、Ruby をまったく知らなかった私がまず最初に面食らったのが下記のような記述です。
{ aaaa: :bbbb }
aaaaコロンスペースコロンbbbb?なにこれ? というのが当時の第一印象でした。
当時の私の気持ちをわかりやすく表現するとこんなかんじです。
というわけで今日は私が aaaaコロンスペースコロンbbbb が何かを理解するまでの過程を記事に残してみたいとおもいます。
: :
という演算子ではないです
お恥ずかしながら、真っ先にイメージしたのは Ruby には : :
という演算子があるのか です。
なので私には一番はじめはこう見えてました。
{ aaaaという変数(?) : :というよくわからない演算子(?) bbbbという変数(?) }
もちろんですがそんな演算子はどこにもありませんでした\(^o^)/
これは Hash らしい
そんな折、{ aaaa: :bbbb }
は Hash ですよ と同僚から声をかけられました。大きなヒントは得られたので、Hash のリファレンスを見てみることにしました。
ハッシュテーブル(連想配列とも呼ぶ)のクラスです。ハッシュは任意の種類のオブ ジェクト(キー)から任意の種類のオブジェクト(値)への関連づけを行うことができます。
ハッシュ生成は多くの場合以下のようなリテラル (リテラル/ハッシュ式) で行われます。
{ a => b, ... } # aはキー、bは値となる { s: b, ... } # { :s => b, ... } と同じ。キーがシンボルの場合の省略した書き方 { "a+": b, ... } # { :"a+" => b, ... } と同じ。上の表現に空白や記号を含めたい場合
連想配列、辞書といえば他言語の経験があれば理解は容易です。もし連想配列という言葉にピンとこない方は こちら をどうぞ。
で、話はリファレンスに戻ります。答えはこの1文です。
{ s: b , ... } # { :s => b, ... } と同じ。キーがシンボルの場合の省略した書き方
Hash の基本は { key => value }
ですが、key がシンボルの場合に限りkey:
と書くことができる ようです。逆に言えば、key:
と書いてあれば key は必ずシンボルであるとも言えますね。シンボルという単語に謎は残るものの、要はこれは連想配列なんだ というざっくりとしたイメージは持てました。
つまり先ほどの例を用いると、aaaa:
と :aaaa =>
は同義である、ということがわかりました。aaaa:
は連想配列のキーなんですね。紛らわしい、なんでコロンの位置が先頭からケツに移動してるんだよ、わかりづらい(言いがかり)
ということでこれで左半分の疑問はほぼ解消できました。
シンボルリテラル
さて、残った疑問です。左側にコロンのついた :aaaa
や :bbbb
というのはいったいなんじゃい?という新たな疑問に悩まされることとなりました。さきほどのハッシュの説明から、:aaaa
も :bbbb
もシンボルというものであるということはわかりました。というわけで続けてリファレンスマニュアルを見てみます。
Symbol って名前の型があるということはわかりました。(浅い)
続けてもう少し見てみましょう。
シンボルオブジェクトは以下のようなリテラルで得られます。
:symbol
:'symbol'
%s!symbol! # %記法
お、`:aaaa` とか `:bbbb` と同じ書き方の話が出てきました。
ちなみにリテラルというのはこちらをどうぞ。
[リテラル (literal)とは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word15346.html)
> 人間語で書いたプログラムの元ネタ(ソースコード)の中に直接べた書きした文字とか数字とかのこと
べた書きというのは例えば `'bbbb'` のような書き方です。これは文字列であることは言うまでもないでしょう。この例のようにべた書きされた文字列を **文字列リテラル** と呼ぶこともあります。
つまりこういうことですね。
```rb
# ベタ書き文字列
'aaaa'
"aaaa"
# ベタ書きシンボル
:bbbb
コロンbbbb の正体はべた書きされたシンボルだったというわけです。数値や文字列以外にもべた書きできるデータがある ということを知らなかった私の世界は狭かったようです。
結論
hash = { aaaa: :bbbb }
↓↓ つまり
hash = { ベタ書きされたSymbol型の値 aaaa => ベタ書きされたSymbol型の値 bbbb }
aaaaコロンスペースコロンbbbbとは、Symbol型のキーと値を持つ連想配列であった ということで私は理解しました。
ところで数字でも文字列でもない Symbol ってどういう型?
※コメントを受けて一部文章を修正しました。
この 非常に言葉で説明しづらいテーマ をすごくわかりやすく説明した先人様の記事があったのでこちらをご参考ください。(他力本願)
Rubyの文字列とシンボルの違いをキッチリ説明できる人になりたい - Qiita
文字列の皮を被った数値。コード上は文字列で見えてるけど内部では数値として扱われる。
リファレンスマニュアルの説明もわかりやすいです。
https://docs.ruby-lang.org/ja/latest/class/Symbol.html
シンボルは、ソース上では文字列のように見え、内部では整数として扱われる、両者を仲立ちするような存在です。
名前を管理するという役割上、シンボルと文字列は一対一に対応します。 また、文字列と違い、immutable (変更不可)であり、同値ならば必ず同一です。
文字列のように書けるけど、内部の振舞いが整数のようになります。つまり同じ名前のシンボルは必ず同じオブジェクトを指すようになります、ということでしょうかね。
おわりに
Ruby のハッシュの記法に触れた記事はもうすでにたくさんありますが、そもそも私のように : :
が演算子と思いこんだり、コロンスペースコロンってなんだ?と思いこんだ人はハッシュの説明に辿りつけない人も(もしかしたら)いるかもしれない、と思ったのでRubyをはじめてさわった当時(とはいっても1年ちょい前くらい)のことを思い出し、あの頃思ったことをなるべくそのままの言葉で記事にしてみました。どこかの誰か一人だけにでもお役に立てればうれしいです。