- プログラミング生産性の核心は、言語そのものよりも豊かなライブラリエコシステムにある
- Ruby on Rails のように、言語の高度な機能を活用したフレームワークは非専門家にも高い生産性を提供する
- しかし、言語の構造的な限界のため、Rails レベルのフレームワークを Java や C で実装するのは難しい
- 言語設計は、書けるライブラリの形と複雑さを直接決定し、これこそが言語発展の本質的な目的である
- Stanza 言語はこの観点から、強力で使いやすいライブラリ生成を可能にする言語設計の重要性を示している
プログラミング言語とライブラリの関係
- ほとんどのプログラミング言語は、変数、配列、ループ、関数など似た基本要素を持つ
- 一部の言語は第一級関数やコルーチンのような高度な機能を提供するが、非専門家はそれらをうまく使いこなさない
- 多くの開発者にとって生産性を高める要因は、言語よりもライブラリである
- たとえば Ruby on Rails は、データベースベースの Web アプリケーションを容易に構築できるようにする
- Rails のおかげで、Ruby 言語自体よりもフレームワークへの選好が強くなる
Ruby on Rails と言語機能の相互作用
- Rails は Ruby のメタプログラミング、実行時評価、第一級関数、ガベージコレクションなど多様な機能を活用している
- 例: ActiveRecords はメタプログラミングを、テンプレートシステムは実行時評価を使う
- イベント処理は、第一級関数をコールバックとして渡す方式で実装される
- Java や C ではこうした機能が不足しており、Rails レベルのフレームワーク実装は不可能である
- Java のメタプログラミングは、ActiveRecords を実装できるほど強力ではない
- したがって Rails は Ruby 言語の構造のおかげで可能であり、言語設計がライブラリの可能性を決める
言語設計がライブラリの形を決める
- C 言語は関数宣言と呼び出しだけで再利用を支援するため、ほとんどの C ライブラリは関数群の形をとる
- Ruby は第一級関数をサポートしており、「ボタンがクリックされたときに実行する動作」を簡潔に表現できる
- 一方 Java ではハンドラクラスを定義しなければならず、コードが複雑になる
- 言語の表現力は、ライブラリの構造と使いやすさを直接規定する
対話型ソフトウェアと拡張可能なフレームワークの登場
- 1970年代のバッチ型コンピューティングでは、関数中心のライブラリで十分だった
- 現代の対話型ソフトウェアでは、拡張可能なライブラリが必要になる
- GUI やイベントベースのシステムでは、「ユーザーがクリックしたときに自分のコードを実行する」という構造が求められる
- Java と C++ は継承とメソッドオーバーライドによって拡張を支援し、こうした構造がフレームワークへと発展した
Stanza 設計の背景と言語の限界
- Stanza の設計動機は、Java で使いやすいゲームプログラミングライブラリを書く難しさから出発している
- Java では並行性を状態機械(state machine)として表現しなければならなかった
- Scheme はcontinuationをサポートしており、より直感的な実装が可能である
- しかし Scheme は静的型検査をサポートしていないため、デバッグ効率が低い
- 現在ほとんどの言語では、型システムをライブラリとして拡張できない
- Stanza は選択的型システム、ガベージコレクション、マルチメソッドベースのオブジェクトシステムを提供する
- ただし、ユーザー定義のオブジェクトシステムを新たに書くことはできない
言語の目的と研究の方向性
- 汎用プログラミング言語の目的は、強力で使いやすいライブラリ生成を支援することである
- 言語が強力であるほど、ライブラリの利用は簡潔になる
- コードは、よく設計されたライブラリを使っているとき、同僚に指示する文章のように読める自然さを持つ
- Racket、Shen、メタオブジェクトプロトコル研究などは、拡張可能な型・オブジェクトシステムを探究している
- 究極的には言語は、「どのライブラリを使えて、どのライブラリを使えないか」によって区別される
- 洗練されたライブラリの背後には、数十年にわたる言語研究と設計の努力が存在する
1件のコメント
Hacker Newsの意見
最も良い例は Prolog だと思う。一般には論理プログラミングの代表的な言語と呼ばれるが、実際には複数の アルゴリズムの集合 にすぎず、各言語のライブラリとして実装できる。Prolog の構文的表現だけを各言語の文法に合わせて提供すれば十分だと思う
10年前は Scala のファンだった。型システムの中で DSL を作れるという「Scalable Language」の概念が魅力的だった。だがコミュニティが JVM 上の Haskell のように使い始めてから興味を失った。最近は WASM や Graal のような技術が言語選択の柔軟性を高めてくれそうで期待している。多くの場合は JS で十分だが、必要なときに Rust のような低水準言語を使える選択肢ができたのは良いことだ
型付きスクリプト言語 で bash を置き換えられたらいいと思う。Elixir で簡単な JSON パーサースクリプトを作ってみたが、かなり良かった
#!/usr/bin/env ocamlでそのまま実行できる。ただし単一ファイルで外部依存関係を自動インストールする機能はない言語とライブラリは 互いに排他的ではない。あるライブラリは事実上言語のように機能し、逆に言語が特定のライブラリのために設計されることもある。たとえば Julia は性能と使いやすさのバランスをうまく取った例だ。高性能コードを Julia で直接書けて、JIT レベルの型特化コンパイル によって最適化された実行を得られる。関数呼び出しモデル自体は単純だが、内部では非常に精巧に動作している
Raku は複数のサブ言語 (slang) を束ねた構造として設計されている。たとえば正規表現、PEG、quoting などをそれぞれのミニ言語として扱い、Slangify を使って独自の DSL を簡単に追加できる
以前、あるシニア開発者が「履歴書に Rails が見えたら即捨てる」と言っていた。言語で人を評価するのが どれほど愚かなことか を改めて感じた
言語やライブラリは結局、機械と人の両方とのコミュニケーション手段 だ。機械とはビットと電圧で、人とは 意図と概念 でコミュニケーションする。したがって言語やライブラリが人にとって明確で素早い表現手段を提供するなら、それが言語かライブラリかは重要ではない。Rails であれ Stanza であれ、目的に合っていてチームが理解しやすければそれが正解だ
自分は「ライブラリこそが最終言語」だと思う。たとえば Ruby on Rails は Ruby を基盤にした優れた Web サービス言語だ。Ruby と Rails は互いのために進化してきた。結局 プログラミングは言語の連続的な翻訳過程 なのだと思う
「言語が強力であるほどライブラリを使いやすくなる」というのはその通りだ。昔の Java では Express のようなフレームワークを作るのは難しかった
C 言語向けの Web フレームワークなら PHP があるじゃないか? ;)