私はJavaScript歴4年のところから、最近になってRubyを書き始めたのですが、こちらの記事に関連して、JavaScriptでは {}
の定義において以下のサンプルの両者の違いをあまり意識しなくてもそこまで問題にはならないと分かったのですが、Rubyだとまた違った記法があり、各々の違いを全然理解できていなかったので改めて調べてみました。
const sample1 = {
id: 1,
name: "name"
};
const sample2 = {
"id": 2,
"name": "name"
};
まず、上記サンプルをRubyで定義すると以下のようになります。
sample1 = {
id: 1,
name: 'name'
}
sample2 = {
'id': 1,
'name': 'name'
}
この場合、sample1とsample2に違いはなくキーはSymbolと呼ばれるオブジェクトになり、sample1[:id]
や sample2[:name]
のようにプロパティを取り出します。
また、Rubyだと以下のように書くこともできます。
sample1 = {
:id => 1,
:name => 'name'
}
sample2 = {
'id' => 1,
'name' => 'name'
}
この場合、sample1とsample2では意味が違ってきます。
違いとしてまずわかりやすいところだとプロパティの取り出し方が異なります。
sample1の場合は sample1[:id]
となりますが、sample2の場合は sample2['id']
となります。
この違いが生まれる理由としては、sample1はSymbol、sample2はStringだからです。
※知らないで使っていると取り出すことすらできなくてハマることになります。。
Symbolが何かというところだと、公式ドキュメントでは以下のように記載があります。
Rubyの内部実装では、メソッド名や変数名、定数名、クラス名などの'名前'を整数で管理しています。これは名前を直接文字列として処理するよりも速度面で有利だからです。そしてその整数をRubyのコード上で表現したものがシンボルです。
シンボルは、ソース上では文字列のように見え、内部では整数として扱われる、両者を仲立ちするような存在です。
名前を管理するという役割上、シンボルと文字列は一対一に対応します。また、文字列と違い、immutable (変更不可)であり、同値ならば必ず同一です。
Ref: https://docs.ruby-lang.org/ja/latest/class/Symbol.html
つまりSymbolで定義した場合immutableとなり、Stringで定義するより高速に処理することができるということのようです。
言語ごとに違いをきちんと意識しないと思わぬところで嵌ってしまうという教訓でした。