Idea

Chat GPTを使ったオリジナルチュートリアルでRustを学ぶ

はじめに

今年に入ってから何度かRustを勉強したいと思って初学者用コンテンツか何かを開いてみるも、だいたい最初の数章でやめてしまっていました。

Rustに限らずなんですが、最初の方の内容は別言語とおよそ似たような内容で退屈で、かといって飛ばしすぎると中腹の内容は全然わからん...となりがちです。

私は偏屈な人間なので「ただのTODOアプリには興味ありません(以下略」という思想のもと、何かしら自分にとって興味あるものを作ることで学習が捗るタイプなのですが、なかなかいい感じの難易度で、その言語の特性を抑えられて、なおかつ自分の興味あるものを作れるコンテンツは転がっていません。
使い慣れた言語の別FWとかであれば自分で考え出せるのですが...。

で、こういった分野はLLMにやらせるのが昨今はよかろうということで、Chat GPTでオリジナルチュートリアルを作ってみたところ、モチベーション高く進められたのでメモを残しておきます。

成果物

コード

https://github.com/IkumaTadokoro/rumdn

実際に書いてみたコードはこちらです。超簡易Markdownパーサーで、#*しか変換できませんが、とりあえずHTMLに変換してくれます。雑な単体テストもあります。

よりみち) リポジトリ名について。もともとRustでMarkdownに書かれたコードブロックを実行できるようにするツールを作ろうと思っていましたが、やめてMarkdownパーサー用のリポジトリに上書きしたという経緯があり、そのツール名が「RuMDn」だったのでリポジトリ名がチュートリアルっぽくありません。Rust でできたMarkdownのなんか、でRuMDnです。読み方は「ラマダン」です。

習得した(はずの)技術

  • 所有権
  • 参照と借用
  • 構造体
  • 列挙型
  • マッチ
  • テストの書き方

歯切れが悪い感じなのは、Chat GPTの返答内容のすべてについて、最新のドキュメントを参照できているわけではないからです。

チュートリアル

チュートリアルの作成

見ればわかる、細かいところは後で自分ではまって学べばよいと思い切り、簡単な部分はすっぱ抜いた上で、Markdownパーサーを作りながらRustっぽいところをいい感じに学べるコースをお願いしてみます。

Arcat2023-08-12-20.55.30.png

良さげな回答が返ってきたので、

いい感じですね。分割して順番に取り組めるとよいです。Rustの概念自体は全く知らないので、中学生が分かる程度の内容で、いくつかのセクションに分けて教えてください。まずはセクションを示してください

と返答してセクションを提示させます。実際に帰ってきたセクションがこちらです。

Arcat2023-08-12-20.58.28.png

なんかRustでよく聞く単語入っている...。良さそうなのでゲームスタートです。

ではセクション1-1からお願いします。途中質問等もあると思うので、私が「次へ」と言ったら次のChapter(セクション)に進んでください。

Chat GPTによるゆるい説明が続く

ミリしらの状態で挑んでいるため自分がジャッジすべきでないことは重々承知ですが、なんとなくゆるい説明が続きます。

Arcat2023-08-12-21.00.27.png

中学生にもわかるように指定したからでしょうか、やたらおもちゃを使って比喩表現が出てきます。中学生はトミカやるのかな...?

Arcat2023-08-12-21.03.23.png

ゆるいとはいいつつも、「次へ」と言わない限りは無限に質問を挟めるので、内容で疑問に思った内容は雑に質問していきます。

冒頭で言語の簡単な部分はすっ飛ばしてよいと指示しましたが、やはり細かい部分で想像できない部分が出てくるので、そういった部分も適宜質問しています。

簡易Markdownパーサーの構築とテスト追加

最初にChat GPTから提供されたコードは以下のとおりです。

fn parse_line(line: &str) -> String {
    if line.starts_with("#") {
        let content = &line[1..].trim();
        return format!("<h1>{}</h1>", content);
    }

    let emphasized = line.replace("*", "<em>");
    format!("<p>{}</p>", emphasized)
}

fn parse_markdown(markdown: &str) -> String {
    markdown
        .lines()
        .map(|line| parse_line(line))
        .collect::<Vec<String>>()
        .join("")
}

fn main() {
    let input = "# This is a header\nThis is *emphasized* text";
    let output = parse_markdown(input);
    println!("{}", output);
}

いい感じに見えるものの、今後自分で機能拡張することと、単純に提供されたロジックがあっていない気がしたのでテストの書き方を聞きます。

Arcat2023-08-12-21.07.57.png

で、教えてもらったテスト方法で単体テストを書いてみたところ見事にバグがあった(空行未対応、1行に複数の強調がある場合に対応できない)ので、これを修正して今回のチュートリアルは終了です。

おわりに

1hくらいで終わるチュートリアルをお願いしましたが、テスト書いたりちょこちょこ調べたり含めて大体1hくらいで本当に終わりました。すごい。

全然プロダクションレベルではないという自覚はありますが、それでも学習を進めるための砂場とざっくりとした知識が手に入ったのは大きいなと思います。新しい言語を始める際には1hくらいでこの形式でまたやってもいいかもしれません。

あと単純にMarkdownパーサーがテストしやすい、自分で考えなくてもパターンが広がりやすくて、自分の中の新しいもの学ぶ際のテンプレに加えてもいいなと思いました(ブログ作るか、HTTPサーバー書くか、Markdownパーサー書くか)。

今年中にMarkdownパーサーが拡張されて、このブログでもwasm経由で使えるようになるといいなあ。