- Javascript っぽい新しい言語を妄想してみた
- Javascript っぽい新しい言語を妄想してみた【配列編】
- Javascript っぽい新しい言語を妄想してみた【マップ編】 ← イマココ
あらすじ
「もしも自分が Javascript っぽい言語をゼロから設計するとしたら?」というテーマで以下のような言語を作ってみました. (名前はまだない)
- 基本的な文法は Javascript と同じ.
- オリジナルの Javascript が「プロトタイプベース」なのに対し, この言語は「クラスベース」なオブジェクト指向.
- すべての値がオブジェクトである. 「スカラー型」あるいは「プリミティブ型」のような概念は存在せず, すべての値が何らかのクラスのインスタンス.
- すべてのクラスは Class クラスのインスタンス. (※新しいクラスの定義は
new Class()
で行う) - 関数の表記はオリジナルの Javascript と同じだが, 引数や返り値のタイプヒンティングを付与することも出来る. (この辺りは Javascript よりもむしろ PHP7 に近い)
詳しいコードは 初回の記事 をご覧ください.
今回は「マップ」についての説明です.
基本形
Javascript における object の概念をこの言語では「マップ」と呼んでいます. 例えば以下のように書けます. Javascript と全く同じですね!
var map = {
"foo": "aaaa",
"bar": "bbbb",
"baz": {
"hoge": true,
"fuga": false,
"piyo": true,
},
"xxxx": ["a", "b", "c"],
"yyyy": 100,
};
console.log(map["baz"]["hoge"]); // true
マップは Map
クラスのインスタンスなので, 以下のようにメソッド呼び出しで書くこともできます.
var child = new Map();
child.put("hoge", true);
child.put("fuga", false);
child.put("piyo", true);
var map = new Map();
map.put("foo", "aaaa");
map.put("bar", "bbbb");
map.put("baz", child);
map.put("xxxx", ["a", "b", "c"]);
map.put("yyyy", 100);
map.put("new", 1.0);
console.log(map.get("baz").get("hoge")); // true
やっぱりジェネリック (総称) に対応
前回の配列編を読んでくださった方はおそらく想像がついているのではないかと思いますが, マップも配列と同様に型を指定することが出来ます.
コンストラクタの引数に Class 型オブジェクトを 2 つ指定することで, キーと値の型をそれぞれ指定することが出来ます.
以下のコードの Integer
および String
は, 言語仕様で定められたグローバル変数 (実態は Class クラスのインスタンス) です.
var map = new Map(Integer, String);
map.put(100, "asdf");
map.put(200, "xyz");
map.put(300, true); // 値が String 型ではないので実行時エラー
以下のようなシンタックスシュガーを使って同じことが表現できます.
var map = <Integer, String>{
100: "asdf",
200, "xyz"
};
map.put("hoge", "fuga"); // キーが Integer 型ではないので実行時エラー
型を指定しない場合は, キーに String, 値に Object を指定したのと同じ意味になります.
以下の map1, map2, map3, map4 はすべて等価なオブジェクトです.
var map1 = <String, Object>{};
var map2 = {};
console.log(map1 == map2); // true
var map3 = new Map(String, Object);
var map4 = new Map();
console.log(map3 == map4);
(余談: 2 つのオブジェクトが「等価」かどうかのチェックは ==
, 「同一」かどうかのチェックは ===
を使います)
例えマップの中身が同じでも, マップに指定された型が違う場合は等価にはなりません.
var map1 = <Integer, Object>{100: "hoge", 200: "fuga"};
var map2 = <Object, String>{100: "hoge", 200: "fuga"};
console.log(map1 == map2); // false
以上で Map 編は終了です. 次回は「クラス定義」編を予定しています. (内容はただいま構想中)
ちなみに ES6 ではかなりクラスベースっぽくなったとの噂ですが, 今のところ最新情報を追えておりません...