Evolutionary Programming and Gradual Typing in ECMAScript 4 (Tutorial) を読む。

Guradual Typingというのは簡単に言うと、コード中で部分的に静的な型情報を記述できて、その範囲で静的チェックができるようになっている型システム。

Evolutionary Programmingというのは、全体を書きおえないと実行できないのではなく、小さな動くコードを書いて、少しづつ大きくしていって最終的に完全なものになるようなプログラミングスタイル。こっちはもともとのECMA Script(というか、スクリプティング言語とよばれるものほとんど)でできている。

つまり、Guradual Typingによって段階を経てWell-TypedなライブラリやアプリケーションにEvolutionさせていけますよ、という感じ。

3ページの右側(ES4)のこぴぺ。"type"定義と、"like"とか、"is like"とか見える。

// Version 2
type Addr = { at: [string, string],
              name: string }

type Msg = { to: [Addr],
             from: Addr,
             subject: string,
             body: string,
             id: uint }

function send(msg: like Msg) {
  msg.id = sendToServer(JSON.encode(msg))
  database[msg.id] = msg
}

function receive()
  handleMessage(-1)

function get(n: uint) {
  if (n in database)
    return database[n]
  return handleMessage(n)
}

var database = []

function handleMessage(n) {
  var msg =
    JSON.decode(receiveFromServer(n))
  if (msg is like { result: string } &&
      msg.result == "no data")
    return null
  if (msg is like Msg)
    return database[msg.id] = msg
  throw new TypeError
}

"like"や"is like"と同様のチェックを実行時にするコードが右側。

function send(msg) {
  validateMsg(msg)
  msg.id = sendToServer(JSON.encode(msg))
  database[msg.id] = msg
}

function receive()
  handleMessage(-1)

function get(n) {
  if (!(uint(n) === n))
    throw new TypeError
  if (n in database)
    return database[n]
  return handleMessage(n)
}

var database = []

function handleMessage(n) {
  var msg =
    JSON.decode(receiveFromServer(n))
  if (typeof msg != "object")
    throw new TypeError
  if (msg.result == "no data")
    return null
  validateMsg(msg)
  return database[msg.id] = msg
}

function validateMsg(msg) {
  function isObject(v)
    v != null && typeof v == "object"

  function isAddress(a)
    isObject(a) &&
    isObject(a.at) &&
    typeof a.at[0] == "string" &&
    typeof a.at[1] == "string" &&
    typeof a.name == "string"

  if (!(isObject(msg) &&
        isObject(msg.to) &&
        msg.to instanceof Array &&
        msg.to.every(isAddress) &&
        isAddress(msg.from) &&
        typeof msg.subject == "string" &&
        typeof msg.body == "string" &&
        typeof msg.id == "number" &&
        uint(msg.id) === msg.id))
    throw new TypeError
}

validateMsg(msg)というのが"msg: like Msg"や"msg is like Msg"に相当するもの。Msgかどうかじゃなく、Msgと同じ構造を含んでいるかどうか、を判定している。msgはMsgにあるメンバーがあれば、余計なものを含んでいてもよい。

"like"は新機能のひとつで、ほかにも"wrap"とかいくつかある(時間切れ、つづく)。