🧅

自作言語Onionの開発がClaude Codeで劇的に変わった話

に公開

はじめに

こんにちは!株式会社ネクストビートでテクノロジー・エバンジェリストなる肩書きでお仕事をしている水島です。最近はLLMのLoRA作成やコーディングAIの活用に力を入れています。

今回は、私が大学生の頃から開発している自作言語Onionの開発において、コーディングAI、特にClaude Codeがどのように役立っているかを紹介したいと思います。

プログラミング言語Onionとは

昔話になりますが、私が大学に入学するにあたって目標としていたことがありました。というか、AC入試の面接でまさにそのことを話したのですが、それは「自作言語を作ること」でした。

その機会は大学2年生の頃にあった「情報特別演習」というプチ卒論のような授業で訪れました。この授業では、自分でテーマを決めて研究を進めることができたのですが、私は迷わず「プログラミング言語の設計と実装」を選びました。

この頃はまだJavaバイトコードについて不案内だったこともあり、JavaソースコードへのトランスレータとしてOnionを実装しました。ただ、自分自身、いずれはちゃんとバイトコードを出力する言語処理系を作りたいと思ってもいたので、その翌年にあった同じ授業ではOnionをバイトコードを出力する処理系に書き換えることを目標にしました。

そうこうして、プログラミング言語Onionは世に生を受けた(?)のでした。当時のOnionは以下のような仕様に基づいた静的型付きオブジェクト指向言語でした。

  • Javaライクなオブジェクト指向言語
    • クラス、継承、インターフェース
    • 例外処理
    • 条件分岐やループなどの制御構造
  • 当時(2004)としてはそこそこ発展的な仕様
    • 代入による型宣言
      • 最初の代入が変数の型を決定する
    • フィールドへの委譲
    • クロージャ
      • 可変ローカル変数のキャプチャ含む
    • トップレベルの文/メソッド
    • ランタイムレス(JREの依存なし)

ただ、今もなかなか治らない私の悪いクセなのですが、一度ある程度動くものができてしまうと細部を詰めるのが億劫になってしまい、放置してしまうことが多々あります。Onionも例に漏れず、大学卒業後は時々思い出したように手をいれるものの、処理系として「使い物になる」レベルには至っていませんでした。

しかし、その状況に風穴を空ける出来事が起こりました。それがコーディングAIの登場です。特にClaude Codeは私のOnion開発に革命をもたらしました。

Claude Codeによる開発の変化

さて、どのようにOnionの開発が変わったのかですが、論より証拠ということで直近のコミットログを見てもらうのが早いかと思います。

Onionのコミットログ

たった二日ですが、大きなところで

  • パターンマッチの網羅性チェック改善
  • 型エイリアスのサポート(ジェネリクスあり)
  • Kotlinスタイルのスマートキャスト

これだけの機能追加を一気にできています。本当に直近では自分で何かを考えて書いておらず、ほとんどClaude Codeに書かせています。たとえば、以下のような感じです:

Claude Codeでのやりとり

Claude Codeによる提案

この例では地味に面倒な最適化や改善案を提案してくれていますが、とりあえず「1.末尾最適化」を選んでみます。すると、早速実装を開始してくれます:

末尾再帰の最適化

あとは放置しておけば、実装が完了します:

末尾再帰の最適化完了

さすがにAIも骨が折れたらしく、数時間かかっていましたが無事実装が完了しました。ただし、あとで確認したところ実装にバグがあったのでさらに修正を依頼しましたが、そこもちゃんと直してくれました。

何はともあれ、今やAIによってかなり機能が拡張されたOnionでは以下のような「モダンな」機能を使ったコードを書くこともできます。

// Extension Methods Sample
// Add methods to existing types without modifying them
extension List[String] {
  def first(): String {
    return this.get(0);
  }
}

extension String {
  def twice(): String {
    return this + this
  }

  def shout(): String {
    return this.toUpperCase() + "!"
  }

  def repeat(n: Int): String {
    var result: String = ""
    var i: Int = 0
    while i < n {
      result = result + this
      i = i + 1
    }
    return result
  }
}

extension JInteger {
  def doubled(): Int {
    return this.intValue() * 2
  }

  def isEven(): Boolean {
    return this.intValue() % 2 == 0
  }
}

// Usage
IO::println(["A", "B"].first())   // A
IO::println("hello".twice())      // hellohello
IO::println("wow".shout())        // WOW!
IO::println("ab".repeat(3))       // ababab

val n: JInteger = JInteger::valueOf(21)
IO::println("" + n.doubled())     // 42
IO::println("" + n.isEven())      // false

val m: JInteger = JInteger::valueOf(10)
IO::println("" + m.isEven())      // true

このコードを実行すると、きちんと意図した通りの動作をします。

A
hellohello
WOW!
ababab
42
false
true

拡張メソッド(ジェネリクス対応)までサクッと実装してくれるのですから本当に大したものです。

おわりに

今回は自作言語Onionの開発においてコーディングAIがどのように役立っているかを紹介しました。正直なところ、ここまでAIに頼り切った開発ができるとは思っていませんでしたが、実際にやってみるとほしかった機能を次々と実現できて、かなり楽しいです。

飽きっぽい私ですがコーディングAIが補助してくれるのなら、この先もOnion開発を楽しく続けられそうです。今後もOnionの進化を楽しみにしていてください!

nextbeat Tech Blog

Discussion