次世代JavaScriptの形

   このエントリをはてなブックマークに登録    2008/2/29

Upcoming Changes to the JavaScript Language」というビデオがありました。 Google TechTalksです。 恐ろしく面白い内容でした。

8年間の標準化活動の成果として今後変化していくJavaScriptの形を紹介しています。 なお、JavaScriptの標準化は未だ過程であるため、ここで紹介された事が将来実装されない可能性もあるそうです。

いや、でも、聞いていて思ったのですがこれはもう違う言語ですね。。。

下位互換があるので今まで作られた物は問題なく動作するはずなのでしょうが、 CとC++に微妙な互換性があるように、互換性をつけたばかりにゴチャゴチャになる事も将来ありそうな予感がしますね。。。 まあ、でも全く違う物として出してしまうと「何それ?ハァ?」という感じで世界に華麗にスルーされてしまうでしょうし、悩ましいところなのだと予想します。

以下、ビデオの要約です。 私はJavaScript初心者なので、要約が間違っているかも知れません。 また英語の誤訳などが含まれているかも知れないので、詳細はビデオをご覧下さい。

JavaScriptの歴史

1996年 Brendan Eichによって元となる言語が作製され、Netscape 2.0の一部として配布された。

1996年 JScriptとしてマイクロソフトがクローンをIE3に組み込む。Netscapeのバグも同様に組み込まれた。

1997年 ECMAによる標準化を要求される。SUNの持つJavaのトレードマークを回避するためにECMAScriptと命名された。可能な限り興味を引かない名前にした。 私(発表者Waldemar Horwat氏)は1998年からこれに関わっている。

1999年 ECMAScript第3版が標準化される。小さな言語変更とライブラリへの細かい追加。

Googleはつい先月にECMAに参加したばかり(2007年11月と推測)。

ECMAScript 4の設計目標

オブジェクト指向プログラミング

static gurantees、static typingが言語に組み込まれている。 型定義ができるようになっている。 タイプ無しの世界とタイプありの世界をうまくミックスする。

もっと最適化ができるように。 ただし、とてもシンプルな実装もできるように。

ECMAScript3との下位互換性は残す。 ただし、非常に特異な特殊例は除く。

古いダイナミックな世界が無くなるわけではない。 それは残る。 dynamicな側面とそうではない側面両方がある。

Block Scoping

新しく加わる機能として、ブロックスコーピングが挙げられる。



function f(a) {
  b = bc;
  g = 0;          //creates a global
  const x = 1;
  if (a) {
    var b = 2;    // hoisted to level of f()
    const bc = 3; // also hoisted to f()
    let d = 4;    // hoisted to prior {
    let const dc = 5; // hoisted to prior {
  }
}


現状では、同じ変数名を持つものは互いに影響を与えあってしまう。 例えば、関数f()中の「var b = 2」は「b = bc」に影響を与える。

新しい仕様では、指定をしないで変数を宣言するとグローバルになる。 新しい「let」を使うと、ブロックに対してローカル変数を宣言できるようになる。

letが有効になる範囲に関しては議論がある。 C++のように、宣言後から使えるようにするか、ブロック内全部で使えるようにするか。

「const」を指定すると変更不能になるという新仕様もある。 ただし、このconstに関してもかなりの議論がある。 constが何をすべきかなど。

Q: JavaのfinalやC++のconstのようなものか?

まず、JavaのfinalとC++のconstは違う。 C++のconstには、二つの意味がある。 アナタは変更できないが、誰かは変更できるかも知れない。 誰も変更できないという意味の場合もある。 ここで言うconstに私が期待するのは、constである物は誰が見ても同じものを見られるものだ。 この宣言が行われる前に変更された場合はどうなるかなどの議論はある。

Q: 一部のECMAScript4機能は実装されてますよね?

はい。一部、Firefoxで実装されています。 ある日突然、全てがリリースされるというよりも、徐々に使える機能が増えていく形でリリースされていくと思います。

let expressions and statements

以下の3つの例は同じ結果になる。



{
  let a = x + y;
  z = a*a;
}

z = let (a = x + y) a * a;

let (a = x + y) {
  z = a * a;
}


Destructuring patterns



var { a,b} = { 5,7} ;

var { foo:c,bar:d} = { foo:'hello', bar:'world'} ;

function swap({ a,b} ) { return { b,a} }


Firefox 2では、この言語拡張は実装済み。

クラス

ECMAScript4にはクラスがある。 ECMAScript3のオブジェクトと同じもの。



dynamic class Point {
  function Point(x, y) {
    this.x = x;
    this.y = y;
  }
  function toString() {
    return '{ ' + this.x + ',' + this.y + '}';
  }
}

var p = new Point(5, 9);


この例のようにdynamic宣言があれば、後からクラスに追加が可能になる。 dynamicがなければ、フィールドを追加できなくなる。 javaで言うところのfinalとは違う。 dynamic宣言が無い場合、インスタンスに対してAd-hocにランタイムに対するフィールド追加ができなくなる。 サブクラスでは、できるが、インスタンスを作ってしまうと、それに対して新しく追加はできなくなるという意味。

javaのinterfaceと同じものもある。

Generic functions



generic function add(v1, v2) : int;

generic function add(v1 : int, v2 : int) {
  return v1 + v2 }

generic function add(v1 : * v2 : *) {
  return 5 }

print(add(4,6));           // 10
print(add(new Date(),6));  // 5


これが使えるのはglobalかつstaticメソッドだけ。 インスタンスに対してはサポートしていない。 オーバーライドのセマンティクスとの組み合わせが、わけワカメになる。

Name Spaces

Nameを守るためのもの。 巨大なプログラムを作るときのもの。 ライブラリなどを様々な場所から取ってきた時などのため。 ライブラリを作るなら、クライアントのプログラム中で衝突しそうな名前は避けなければならない。



namespace ns1;
namespace ns2;

ns1 var x = 1;
ns2 var x = 2;

print(ns1::x); // 1
print(ns2::x); // 2


この仕組みを使って、ECMAScript4はクラスでのprivateとpublicを実現する。 具体的には、クラスを作るとprivateとpublicというネームスペースが生成される。

Javaと違うのは、自分でprivateとpublicのように振舞えるネームスペースを作れるところ。

Package

複数のファイルを跨いで機能を実現するためのもの。 複数のファイル間で宣言可能。 publicとinternalを分けたりできる。

file1.es



package com.google.demo {
  internal var motto = "don't be evil";
}


file2.es



package com.google.demo {
  public function getMotto() { return motto; }
}

import com.google.demo.*;
print(getMotto());
print(motto);


Program units



unit DrawOnTheEarth {
  use unit GoogleMaps http://maps.google.com/es4api;

  function drawLine(...) { ...

  function drawBezierCurve() { ...
}


URLでunitを指定するのは提案されているが、まだ最終段階ではない。

Mixing dynamic and static typing

JavaScriptは歴史的にdynamic language。 型という概念がなかった。

型指定を出来るように言語を拡張



var i : int = 7;


上記例ではiはint型しか持てない。 型が指定されていないものとの組み合わせを考えてあり、誰とでもコンパチなスター型タイプというのも存在する。

Types

クラスやインターフェースなどのlanguage constructによって使われる。


int,string,RegExp

他のタイプから構築


union types {string,int}
record types {name:string, age:uint}

他のnameへエイリアス


type Point = {x:double, y:double}

union typeはC++ unionとは違う。

Nullability and optionality

nullとundefinedは関連する型がある。 型に対してnull(もしくはundefined)を含むかどうかを指定できる。

null可能なタイプは「T?」。そうでないものは「T!」。

デフォルトでは数値やブーレアンはnon-nullable。その他はnullable。

Q: バックワード互換のためにこれをしている?

いや、そういうわけではないと思う。 javaに似ていると思う。



var b : boolean ? = null;

var i : int = null;  // 駄目,エラー

var d : Date = null;

var f = function(int, int*) : int *...


Functional Types



specify parameter and return type
function(string, int, boolean) : boolean

support for variable length arguments
function(...{string}) : string

constructed type

function(this:Boolean, *) : boolean


Parametrized types



type Map. = ...

class Pair. {
  var first : T;
  var second : T;
}


Like and Wrap

like型はpreconditionのようなもの。

wrapには2つある。value operatorとtype operator。


var v = {x:"hello"} wrap { x:string, y:boolean}

wrap type operatorはlikeチェックを行い、valueをwrapする。

Like



function isHalloween(d : like Date!) {
  return d.getMonth() == 9 && d.getDate() == 31;
}


Pseudo-Javaと比較



boolean isHalloween(Object o) {
  if (o instanceof Date && o != null) {
    Date d = (Date) o;
    return d.getMonth() == 9 && d.getDate() == 31;
  } else {
    throw new TypeError();
  ]
}


for (... in ...)とfor each (...)

for (... in ...)はES3に含まれるが、数値プロパティのみをイテレートする。

新しいオブジェクトは「IterableType」になり、自作イテレータを持つことができるようになる。



for each (let n in {1,2,3}) {
  print(n);
}


Decimal arithmetic(10進演算)

IEEE754の丸め演算は最も報告されるES3「バグ」である。 https://bugzilla.mozilla.org/show_bug.cgi?id=5856

14.28*9 = 128.52だけど、ブラウザは128.5199...9と言う。

ES4はIEEE754r 128ビット10進演算をpragmaでenableできる。



ctx = new DecimalContext(...)
{
  use decimal ctx;
  x = a + b;
}


これに関しては何年も議論した。

Strict mode

「use strict」pragmaを使って、ES3では大丈夫だけどES4ではエラーになるプログラミングエラーを発見できる。

例えば、

  • 引数の数を間違えてfunctionを使う。
  • 存在しない変数を使ってしまう。
  • 既知の型を持つnon-dynamicオブジェクトに対して存在しないプロパティを使う。
  • 既知の型を持つオブジェクトから削除不能なプロパティを削除してしまう。
  • constな値を変更しようとする。

最後の議論の中で。。。

マイクロソフトはIE7にはES4を入れないと言っているらしい。 もしかしたらIE8に入れるかも知れない。 そもそも、ES4がIEに入る事は無いかも知れない。

これに関わっている企業は、AdobeとOpera、Mozilla。 なので、いくつかの実装はそのうち出てくるだろうと思う。

p.s.

Japan Blog Award 2008の最終選考(投票中)に残りました! Geekなぺーじは、かなり下の方にひっそりと登場しています。

   このエントリをはてなブックマークに登録