世界を動かす技術を、日本語で。

LLMはDSL設計者にとって興味深い課題を提起する

概要

  • LLM時代 におけるプログラミング言語設計の課題と変化
  • DSL(ドメイン特化言語) の意義とLLMによる影響
  • Pythonなどの一般言語 でのLLM性能の高さとDSLへの影響
  • LLMとDSLが 共存・協調 するための新たな設計方向性
  • 今後の 言語設計の発展と課題 の整理

LLM時代のプログラミング言語設計:平凡への回帰か?

  • Programming Language(PL) Design の魅力は、特定ドメインに合わせた 直感的なインターフェース の提供にあり
  • DSLによる 高レベルな記述 で、冗長なAPI呼び出しを排除し、 バグや認知負荷の低減 を実現
  • 「正しさの保証」 を言語自体で担保する設計思想
  • しかし、 LLMの台頭 で「なぜDSLを作る必要があるのか?」という疑問が生じている現状
  • LLMの普及により、 DSL設計の意義や将来性 が再考される状況

LLMの課題:Pythonで全てが簡単になる時代

  • LLMの学習データ はPythonやJavaScriptなど一般的な言語に偏重
  • 研究によると、 低リソース言語やニッチなDSL ではLLMの性能が著しく低下
  • DSLを使う場合、 LLMによるコード生成の恩恵を受けにくい という問題
  • DSL設計の コスト増大 と、利用者がLLMの利便性を失うリスク
  • 今後、 DSL開発の停滞や障壁の増加 が懸念

言語設計の新たな方向性:LLMとDSLの共存

  • LLM時代における 言語設計の進化 を模索する必要性
  • 以下の3つの方向性が有望

1. Pythonを介したLLMへのDSL知識伝達

  • DSLの 構文や意味論 は既存言語と大きく異なるため、LLMが理解しにくい
  • 研究例:「 Verified Code Transpilation with LLMs」では、LLMにまず Pythonで記述 させ、後でDSLに変換する手法
  • Pythonを 中間言語 として活用し、DSL向けコード生成の精度向上
  • DSL設計フレームワークに LLMフレンドリーなPython記述 を自動生成・検証する仕組みの提案
  • DSL実装からPython表現を自動抽出 し、LLM活用を容易にする可能性

2. LLMによるインフォーマルとフォーマルの橋渡し

  • LLMは「 スクリプト生成」など、非定型的な作業で特に有用
  • 例:ユーザーが 高レベルな仕様 を自然言語で指示し、LLMが「つなぎコード」を生成
  • フォーマル(厳密なコード)とインフォーマル(自然言語指示)の ハイブリッドな開発フロー
  • DSLにおいても、 自然言語による仕様記述と連携 できる設計が求められる
  • DSLの型・解析情報から 自然言語仕様を自動生成 するアプローチの可能性

3. 検証可能なLLM合成のための言語設計

  • LLMによるコード生成を 検証言語 (例:Dafny, Boogie等)で保証する研究が活発化
  • LLMが生成したコードの 正しさを検証 するための 仕様記述言語の設計
  • LLMと検証技術の 連携による信頼性向上
  • 仕様記述とコード生成を 統合的に扱う新しいDSL設計 の可能性

今後の展望と課題

  • LLMの発展とともに、 言語設計の役割や価値 が問われる時代
  • DSLの意義 を再定義し、LLMと 協調可能な設計手法 の模索が不可欠
  • LLMの得意領域とDSLの強みを 補完し合うアプローチ の重要性
  • 開発者・研究者間の議論とフィードバック を通じた、言語設計の新たな展開への期待

Hackerたちの意見

最近、ロボットフレームワークのDSLを使うことになったんだけど、あんまり好きじゃないな。ビジネスユーザーにとって、命令型コードよりも読みやすいとは思えないし。どのDSLも新しいAPIを覚えなきゃいけないし、だいたいは落とし穴だらけだよね。直感的な使いやすさは見る人によるって感じ。俺がやりたいのは、命令型コードを自然言語でテスト内容を説明する形に変換して、エイリアスとかの設定を加えることかな。

DSLって一様じゃないよね。MiniZincを考えてみて。これはすごくクールで、制約解決問題を書くのに役立つし、いろんなバックエンドソルバーで実行できるんだ。中間言語やバイトコード(LLVM自体も含めて)は、よく定義されたプリミティブを使って低レベルの操作を表現するための便利なDSLだよ。コード生成DSLも特定のアプリケーションには素晴らしいし、特にカスタムボイラープレートを作るのに役立つ。シナリオに特有のことをDSLで書いて、テンプレートベースのコード生成が提供されたデータを使ってターゲット言語のコードを生成するっていうのは、すごく柔軟なアプローチだね。これは言語指向プログラミング(LOP)のいくつかのタイプのうちの一つに過ぎない。

DSL(ドメイン特化言語)全般には懐疑的じゃないけど、ロボットフレームワークについては同意するよ。HTMLの出力フォーマットは結構いいと思うけど、テストケースのタグの使い方には不満があるし、非トリビアルなものを書くのはイライラする。Pythonの拡張を書くのは簡単だから、結局「ビジネスロジック」以外のロジックはほとんどPythonで書いちゃった。一般的にはそうするべきなんだろうけど、その時点で全部Pythonか好きな言語で書いた方が良さそうだね。

もっと多くの人がこの話をしてるのを見るのはいいね。6ヶ月前にこれについて書いたんだけど、LLMの使い方が多くの人を古いプログラミング言語やフレームワーク、基本的なデザインに戻らせてるのに気づいたんだ。正直、これは必ずしも悪いことじゃないと思うけど、新しいDSLやフレームワークに対して抑圧的な影響があるのは確かだね。これは解決不可能な問題じゃないと思うけど、特に今は人気のあるコーディングエージェントがカスタムドキュメントコンテキストを持つMCPサポートを提供してるからね。でも、LLMにはトレーニングデータが一番多いランタイムやフレームワークにユーザーを引き寄せる強い力が常にあると思う。

それは素晴らしいブログ記事だし、非常に興味深いポイントだね。うん、LLMが既存の言語のフレームワークにどう影響するか考えてなかったけど、既存のものを強化して革新を抑える似たような効果があるのは納得できる。DSLのこの影響を解決するのはフレームワークよりも少し難しいかもしれないと思う。なぜなら、DSLは意味が全然違ったりするから(例えば、Prologのような論理プログラミングDSLと、Haskellのような関数型DSLを想像してみて)。だから、MCPの枠組みにうまくはまらないかもね。でも、解決不可能ではないと思うし、もっと研究が必要だね。

今日、これに関するいい投稿を見たよ…

言語学や言語の歴史に詳しい人たちへ:印刷機が普及するにつれて、話し言葉の進化が遅くなる現象が観察されてるって知ってる?それと、「国際英語」って、似たような現象の観察なのかな?

スカイネットはCで動くよ。

自動翻訳ツールがこれを緩和する手助けになるかもしれないと思う。もしかしたら、PythonやJavaなどから新しい言語に翻訳するための別のニューラルネットワークを訓練するのもありかもね。

健全だと思うよ。だって、高度な抽象化の塔を作ることに対抗する流れを生むからね。それが大きな問題なんだ。スタックが深くなって、より「スイスアーミーナイフ」みたいな言語を作ることになる。そうすると、私たちにとっては便利だけど、他の誰かが後で世代ごとの「溶岩層」を解読しなきゃいけなくなる。市場のトレンドが変わって、新しいものが古いものに取って代わるときにね。新しいやり方としては、スイスアーミーナイフの代わりに使い捨てのジグを作ることだ。LLMを使えば、DSLとして十分に機能するプロンプトを与えて、プレースホルダーコードを立ち上げられる。そこにシニア開発者のタッチが必要な重要な要素を補えばいい。結果的にコードは原始的に見えるし、原始的な動作をするけど、最初は多くの不一致を生む。でも、長期的にはメンテナンスには問題ないよ。原始的なコードは抽象コードに「収穫」しやすいけど、その逆は簡単じゃないからね。

新しいフレームワークだけじゃなくて、新しい機能もあるからね。例えば、iOS 26の機能を使ったコードを書くためにLLMを使うのは難しいと思う。単にLLMに機能についてのドキュメントを注入させるだけじゃうまくいかないんじゃないかな(誰かがこれを研究したかもしれないけど)。彼らが「よく知られた」ことを上手にやれるのは、実際の例がたくさんトレーニングされているからなんだよね。

これ、Coders at Workの第13章、フラン・アレンの抜粋を思い出すな。セイベル: 最後にプログラミングしたのはいつだと思う? アレン: ああ、かなり前だね。Cが出たときにやめちゃったんだ。それが大きな打撃だった。最適化や変換でかなりいい進展があったのに、次々と素敵な問題を解決していってたんだ。Cが出たとき、SIGPLANのコンパイラ会議で、Cを支持するベル研究所のスティーブ・ジョンソンと、当時自動最適化のプロジェクトに取り組んでいたビル・ハリソンの間で議論があったんだ。その議論の核心は、プログラマーが最適化を気にしなくてもよくなるというスティーブの主張だった。Cのデザインの動機は、高水準言語では解決できなかった三つの問題だったんだ。一つは割り込み処理、もう一つはリソースのスケジューリング、そして三つ目はメモリの割り当て。高水準言語ではそれができなかったから、Cの言い訳になったんだ。セイベル: Cをオペレーティングシステムのカーネルに限定して使うのは合理的だと思う? アレン: ああ、それはいいと思うよ。実際、専門家が大きなボトルネックなしに微調整できる何かが必要だからね。それが解決すべき重要な問題なんだ。1960年には、リスプ、APL、フォートラン、COBOL、Algol 60といった素晴らしい言語がたくさんあった。これらはCよりも高水準なんだ。Cが発展してから、私たちは本当に後退してしまった。Cは自動最適化や自動並列化、高水準言語を機械にマッピングする能力を奪ってしまった。これが、コンパイラが大学であまり教えられなくなった理由の一つだよ。

正直言って、これは必ずしも悪いことだとは思わないよ。君は本当に、コンピュータサイエンスの最初の50年で完璧を発見したと言えるの?化学の最初の50年では、まだフロギストンを信じてたしね。

LLM(大規模言語モデル)が高水準言語に対するコンパイラのようなものであるっていう比喩をよく聞くけど、あれはひどい比喩だよね。でも、実際にそうなる可能性もあるから侮れない。もしそうなったら、コンパイラの登場がアセンブリコードの使いやすさやエルゴノミクスを改善するインセンティブを完全に消し去ったことを考えてみて。アセンブリコードはずっとクソみたいなもので、今もそうだし、誰も気にしないからね。高水準言語もそんな未来が待ってるかもしれない。これが終わりの始まりかも。

重要なポイントは信頼性だと思う。信頼が高いからこそ「ジュニア開発者がコンパイラのバグだと思ってる」っていうジョークが成り立つわけで。もしコンパイラに重大な非決定論的エラーがあって、信頼できる修正がなかったら、全然違う未来になってたかもね。

大きな違いは、コンパイラは決定論的だってこと。コーダーは生成されたアセンブリをレビューしたりパッチを当てたりしないからね。LLMがそんな風に機能するとは思えない。常に「ねえ、LLM、これをコーディングして」とか「いや、関数fはちょっと違うから、これをやって」とかのやり取りになると思う。これはPhotoshopで見られるものに似てる。ピクセルを手動で編集したり、決定論的なツールを使ったり、AIを使ったりできる。最終的な結果が大事なら、たぶん三つを組み合わせて使うだろうね。事前にLLMに仕様を提示して、コードを見ないなんてことはないと思う。つまり「英語を高水準のコーディング言語として使う」ってことはない。理由は、コードは論理を英語で全部説明するよりも簡潔で明確だから。詳細が気にならず、柔軟性がある場合には、英語をコードのように使えるかもしれないけど、ビジネス関連のケースでは、実際のコードが長い間中心になると思う。

無知な視点だね、アセンブリを一度も書いたことがない人からの意見かも。アセンブリはターゲットにするシステムに結びついていて、実際には「改善」できないんだ。ただ、マクロを使ってエルゴノミクスを大幅に改善することはできるし、みんなそうしてるよ。

LLVM IIRがあるけど、アセンブリに似てるけど、もっと良くてポータブルだよね?そこから何か観察できるかも。似たような仕事をするけど、実際に残る仕事にとってはより良い方法でやってるんだ。

なんか混乱してるな。 > 「突然、DSLの機会コストが倍増した。LLMの世界では、DSLを構築・設計する投資だけでなく、エンドユーザーはDSL用のコードを生成するためにLLMの使用を犠牲にしなければならない。」 彼らはそうしないと思うよ。DSLの簡潔な説明と例を提供すれば、LLMはそのDSL内でのコーディングが得意になるはず。エラーを提供できれば、エージェントもさらに良くなると思う。記事もその方向に行ってる気がするけど、DSLの作成はLLMが他のプログラミングタスクよりも助けられる部分だと思う。LLMはデータパイプラインを生成するのが得意だからね。

それは確かにDSLによるよね。既存のプログラミング言語に近い意味論を持っているなら、いくつかの例で十分かもしれないけど、特定のドメインがあまり一致しない場合はどうなる? 例えば、編み物用の言語やストリーミングを表現するための非決定論的言語など、DSLを設計するのが難しいドメインの例があるよね。私の主な懸念は、LLMが日常的なタスクには優れていても、よりエキサイティングな進展には苦労するかもしれないってこと。そうなると、進化するDSLを考えるための活性エネルギーが増して、結果的に分野が停滞するかもしれない。

これも私の見解に近いかな。今のところ、ほとんどのバイブコーディングは、LLMがやるのが安くて簡単だから、たくさんの重複を生んでるよね。でも、コーディングアシスタントを使った作業が複雑になるにつれて、LLMも人間と同じように大量の重複コードを扱うのが得意ではなくなると思う。限られたコンテキストサイズを考えると、より少ないトークンでより多くのロジックを収められるDSLがあれば、DSLの重要性が減るどころか増すかもしれないね。

同じ文を貼り付けて、ほぼ同じことを言おうとしてたところだった。さらに付け加えると… 新しいDSLに対するLLMの制限の一つは、LLMがオープンソースコードから直接盗作する可能性が低いことかもしれない。それが一つの特徴になるかも。もう一つの特徴は、ユーザーが自分の作業をして、AIの手抜きや盗作で「宿題をカンニングする」代わりに、より良い仕事をすることかもしれない。学校でも職場でもね。

機械レベルのアセンブリ命令以外のすべての言語は、ヒューマンリーダブルなコードとしてDSLだよ。

俺も6ヶ月前にLLMによるスタックの硬直化の可能性について長々と書いたよ:https://paritybits.me/stack-ossification/ その時、最初の本格的なバイブコーディングアプリを作るときに、Claude 3.5のPythonの好みに屈してしまった。Pythonはそれ以前も以降も一行も書いたことがないけど、波に乗ってしまったんだ。Claudeと一緒に行き詰まって、無知な俺は修正を諦めて、そのままソフトウェアを完成させたことにした。今は、自分のローカルなウィスパー音声認識アプリに完全に依存している小さなモンスターのオーナーになったよ。以来、スタックの硬直化について考え続けてる。最近、LLMを使ってanimejs v4を使おうとしたときにフラストレーションを感じたから、まだ可能性があると思う。animejs v3とv4の間には大きなAPIの変更があって、コンテキストを考慮した指示やドキュメントがあっても、モデルがv3 APIに対して書くのを止められなかった。スタックの硬直化から抜け出す方法は二つあると思う。一つは明らかで受動的な方法で、フロンティアモデルが内部化された知識(トレーニングデータから)を「脇に置く」ことで、コンテキスト内の指示やドキュメントRAGソリューションを優先すること。ここはあまり楽観的じゃないな。これらのモデルは本質的にヒップショッターだし、賢くなるにつれてこの反射が強くなる気がする。ただ、Sonnet 4は一般的に3.7よりも指示に従うのが上手だから、もしかしたら。もう一つの明らかでない方法は、特定の依存関係のバージョンに対して多くのキャッシュされたマイクロファインチューニングに基づく大規模なモデル統合のようなもので、各ワークスペースコンテキストが誤ったバージョンの依存関係を特定のフィンチューニングで排除したカスタマイズされたLLM(LoRAスタイル)を呼び出せるようにすることだ。

LLM時代に新しいDSLを作るのは必要ない気がする。DSLは、シンプルなパーサーが扱えるコンパクトでドメイン特化の構文を提供していたから意味があった。でも、現代の言語モデルは主流の言語を楽に読み書き説明できるし、それらの言語の周りのツール—REPL、コンパイラ、デバッガ、ライブラリ—は、自分で作るものとは比べ物にならないくらい進んでる。だから、また新しいミニ言語を発明するより、確立された言語を活用して、LLM(とその成熟したエコシステム)に重い作業をやらせればいいんだ。

LLMに動作するJavaコードを書かせることすら信頼できないのに、DSLが表現すべきものを別の形に変換することを信頼できるわけがない。確かに、トレーニングセットにJava 23が十分に含まれていないかもしれないけど、Java 11と10年前のライブラリの組み合わせなら、これらのコーディングLLMが本物なら問題ないはず。LLMが便利さから言語機能やメソッド、演算子を勝手に作り出す限り、DSLはここに残るだろうね。

ビジュアルプログラミングへの影響について考えてる。どんなビジュアルプログラミング環境も、人間が読み書きできるテキスト表現との完璧なラウンドトリップが必要だとずっと信じてきた。理由はいろいろあるけど—バージョン管理、自動化、テキストファイル周りの数十年のツールを活用すること、テキストの方が簡単なタスクもあるからね—LLMはこのリストにもう一つ理由を加えた。

いいね。それをLLMがソフトウェア開発環境に与えるポジティブな影響の一つとして記録しておくよ(神様、あまり多くないけどね)。DSLの増殖は問題だ。これは多くの人が聞きたくないことだと知ってるし、その気持ちには共感するよ。賢い人は複雑さやエレガンスに惹かれるし、賢い人は解決策を作るのが好きだから、DSLは複雑でエレガントな解決策なんだ。わかるよ。でも問題は、解決策が多すぎると複雑さが生まれ、複雑さは[Grug]の永遠の敵なんだ。他の問題領域がそれぞれ独自の言語を必要とするわけじゃないし、既存の言語は多くの異なる問題領域に適応できるように設計されてる。もしLLMが、そうでなければ野生的に成長するはずのいくつかのDSLの成長を抑える手助けをしてくれるなら、私はそれに対してはまあまあ納得できるかな。

これは生存者バイアスのように感じるな。昔のツールたちは、かつては新しくてかっこいいDSLだったように思える。今はもう、長い間使われてきたから、確立されたものとして尊敬されてるけどね。でも、使えなかったダサいDSLが千個あったとしたら、その中から一つ、新しいツールがソフトウェア開発を新たなレベルに引き上げたんだよね。1960年にLLMが登場したパラレルユニバースについても、同じことが言えるかな?

タイトルは「DSLはLLMユーザーにとって興味深い問題を提起する」ってすべきだね。コーディングにおけるLLMが、ある約束(と仮定)に基づいて推進されているのは重要だよ。それが、技術が社会的に受け入れられると瞬時に完全に逆転する瞬間があるからね。「今は誰でもコーディングできる!」→「みんなは、生成されたコードをプロンプトしたりテストしたりするための高度に専門的な技術を学ばなきゃならない」。「LLMは賢くて、既存の技術と簡単にインターフェースできる」→「今すぐこれらのエージェントプロトコルを採用しなければならない」。「LLMは0-shot学習が得意」→「この言語/ライブラリ/ツールのバージョンは使わない、だって私のモデルはその例でトレーニングされてないから」。「LLMは既存のコードを簡単に理解する」→「あなたのコードはLLMが理解できるように特別に変更しなければならない」 これ、かなり馬鹿げてるよね。

グラフを持ってこさせないでくれ。 https://upload.wikimedia.org/wikipedia/commons/9/94/Gartner_...

私はDSLが好きじゃないな。確かに、最適なツールになるケースもあるかもしれないけど、一般的にはDSLを使っているプロジェクトに参加する人にはかなりの学習負担がかかるんだよね。DSLプロジェクトがいくつか枯れてしまったのを見たことがあるけど、誰もそのDSLを学びたがらなかったからだよ。知識と時間の投資が、将来の他の何かに転用できないからね。私の個人的な意見としては、DSLは見栄のプロジェクトだと思う。適切なメソッドや関数を追加することで、DSLの明快さやシンプルさにかなり近づけることができるんだ。派手な構文糖は得られないけどね。もしかしたら、DSLは人間にとって「書き込み専用」言語なのかも。誰かに不幸や悲しみを願うつもりはないけど、LLMがDSLを絶滅させても全然気にしないよ。

私の意見では、DSLにアプローチする最良の方法は、かなり柔軟な構文を持つ既存の言語を使うことだね。私たちはグルービーでこれをやって、かなりうまくいったよ。もしもう一度やるとしたら、業界での関連性が高そうなコトリンかルビーを選ぶかもしれないな。既存の言語をベースに選ぶ美点は、最初から広範な標準ライブラリが得られることなんだ。だから、あなたの「DSL」作成者としての仕事は、そのDSLの作成者にとって意味のある価値を提供することに基づいているんだ。私たちには、あらゆる種類のランダムなゴミ(メール、エクセルドキュメント、CSVファイル、PDFなど)を解析して処理しなければならないデータ取り込みパイプラインがあるから、特にうまくいってるよ。グルービーやルビー、コトリンのような言語は、あなたのドメインの問題に合った形で構文に拡張を追加するのが簡単だから、すごく合ってるんだ。タイプスクリプトも似た理由で悪くない選択肢だけど、考えない理由は、私たちがJVMバックエンドを運用していて、タイプスクリプトをJVM用に解析するのがちょっと面倒だからだね。