2014-09-23

理想の言語とは何かを考える

no_image.jpg

[ PR ]


前回まで、過去を知ることでどう変わってきたかを見てきました。

今回は、未来を想像して見たいと思います。プログラミングをしている皆さんなら、きっと使っている言語の進化を実感していることでしょう。

そんな言語の進化は、今もどこかで誰かが、何らかのインスピレーションを受けて行っています。

そこで、今回は理想の言語とは何かを考えてみたいと思います。

(今回は私が理想とする条件なので、人によって変わってくると思います)

理想の言語の条件

挙動

  • コンパイルが速い
  • 動作が速い
  • 起動が速い
  • メモリ使用率が小さい

この2つは基本的な言語の性質ですね。全てを満たすことは難しいですが、改善する努力が必要でしょう。

例えば、Javaは動作は速いですが起動は遅く、起動を高速化する努力が一層必要です。

言語仕様

  • 標準的な構文を用いている (ECMAScript 4〜6 を参考に)
  • 学習コストが低い
  • 変数定義が型宣言で始まらない (var foo:Foo = ...)
  • 関数名が短い (Objective-Cは最悪)
  • セミコロンが不要 (Pythonなど)
  • 必ずしもクラス定義が必要でない (スクリプト言語として使いやすい)
  • eval が存在することが望ましい (メタプログラミングの可能性)
  • 低レイヤーへのアクセスが言語と独立している (JNIなど)
  • 基本構文が少なく、ほとんどが高階関数で定義されている (Scalaなど)
  • 静的型付け言語であれば、型推論ができる。(OCamlなど)
  • 関数は全て第一級関数である (Scalaなど)
  • 値は全てオブジェクトである (Rubyなど)
  • シンボル(キーワード)が存在する (Rubyなど)
  • デフォルトのモデレータはPublic (Scalaなど)
  • 無名関数のシンタックスシュガーがある (x) -> x*x
  • ほとんどの構文が式であり、値を返す (Rubyなど)
  • 最後の式を返り値とする (Rubyなど)
  • インラインドキュメントが書ける (JavaDocなど)
  • アノテーションが書ける (Javaなど)
  • コンストラクタは def initialize(...) とする (Rubyなど)
  • シンタックスシュガーを複数用意する (Rubyなど)
  • 暗黙の宣言による副作用は極力避ける (Scalaは最悪)
  • 演算子のオーバーロードを制限付きで許容する (Rubyなど)

これらの性質は、可読性に優れ、スケーラブルであることが既に示されています。

また、高階関数を活用することで、より完結で学習コストの低い言語仕様が策定できます。

仮想マシン (VM)

  • VMを再発明しない
  • VMの起動が速い
  • VMのメモリ使用が少ない
  • GCのオーバーヘッドが小さい
  • VMに限らないが、末尾再帰最適化をサポートする

VMは難しいところですが、JVMNekoVMLLVMのように、VMとして独立したものを利用することが、開発コストを下げ、VMの性能を向上させることに繋がると思います。

ライブラリ

  • importができ、別名を付けることができる (Scalaなど)
  • 部分importができる (Scalaなど)
  • 標準ライブラリが充実している (Pythonなど)
  • gemのようなバージョン管理システムがある (Rubyなど)

使用例(Examples)

Hello World

println "hello world"

条件付きで、括弧の省略を認める。

Fib

def fib(n: Int): Int {
    if(n < 2){
        n
    }else{
        fib(n-2) + fib(n-1)
    }
}

if式は値を返し、最後の式が返り値となる。

クラス

class Say<T> {
    var form: String

    def initialize(format: String){
        this.form = format
    }

    // 演算子のオーバーロード
    def [](val: T){
        println String.format(form, val);
    }
}

var say = new Say<String>("hello, %s"); // 型推論
say["world"]; // hello, world

Map

def double(list: List<Int>): List<Int> {
    list.map(n -> n*2) // 型推論
}

p double([1,2,3]) // [2,4,6]

Filter

def odds(list: List<Int>): List<Int> {
    list.filter(n -> n.odd?) // 型推論
}

p odds([1,2,3,4,5]) // [1,3,5]

Inject

def sum(list: List<Int>): Int {
    list.inject(:+)
}

p sum([1,2,3,4,5]) //  15

Fold Left

def join(list: List<String>): String {
    list.foldL(_ + _) // シンタックスシュガー
}

p join(["hello", " ", "world"]) //  (("hello" + " ") + "world") => "hello world"

Fold Right

def subRev(list: List<Int>): Int {
    list.foldR(_ - _) // シンタックスシュガー
}

p subRev([1,2,3]) //  (1 - (2 - 3)) => 2

マップ(辞書)

var ages = ["Tom": 16, "Mary": 21, "Bosh", 34] // 型推論

p ages.keys.filter(key -> ages[key] < 20) // ["Tom"]

マクロ

macro def nil!(expr: Expr){
    "#{expr} = nil"
}

var a = "foo"
nil!(a) // コンパイル時に実行

まとめ

今回は理想の言語を自由に考えてみました。

同じことを自分でやってみると、案外楽しいと思いますよ。

ふつうのコンパイラをつくろう 言語処理系をつくりながら学ぶコンパイルと実行環境の仕組み
青木 峰郎
ソフトバンククリエイティブ
売り上げランキング: 246,711

コメントはTwitterアカウントにお願いします。

RECENT POSTS


[ PR ]

.