新しいプログラミング言語Carbonで実際にFizzBuzzしてみた

勤め先のブログに「CarbonでHello Worldしてみた」みたいな記事を書いたのですが、自分でかいたコードを動かすところまでできず消化不良気味だったので、この記事でFizzBuzzをかいて動かすところまでやってみます。

## Carbonとは

Googleが新しく2022年7月20日に発表した新しいプログラミング言語です。PHPの日時操作ライブラリ[^1]ではありません。

https://github.com/carbon-language/carbon-lang

**C++の後継となる言語**を目指しているとのこと。Rustでいいじゃんという方はそれでいい[^2]そうです。

見た感じ、CarbonからC++の既存モジュールを利用したり、反対にC++から新しくCarbonで作ったモジュールを呼び出せたり、生のポインタを扱えたりといった特徴があります。既存のC++プロジェクトをRustにしてリファクタするのは大変みたいな状況で、Carbonを取り入れるような使い方を想定しているのでしょうか。

英語が分かる方は[CppNorth 2022の動画](https://www.youtube.com/watch?v=omrY53kbVoA)を見ると良いと思います。英語が分からない私は雰囲気だけ理解しました。



## Hello World

[READMEのGetting started](https://github.com/carbon-language/carbon-lang#getting-started)にしたがってHello Worldしてみます

### 環境を準備する

Ubuntu 22.04 LTS（Windows 10 の WSL2）でやります。

まず必要となるHomebrew[^3]を導入します。[このページ](https://brew.sh/)のコマンドでインストールしてから、[このページ](https://docs.brew.sh/Homebrew-on-Linux)にあるコマンドでパスを確認します。

```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

test -d ~/.linuxbrew && eval "$(~/.linuxbrew/bin/brew shellenv)"
test -d /home/linuxbrew/.linuxbrew && eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
test -r ~/.bash_profile && echo "eval \"\$($(brew --prefix)/bin/brew shellenv)\"" >> ~/.bash_profile
echo "eval \"\$($(brew --prefix)/bin/brew shellenv)\"" >> ~/.profile
```

導入したbrewでbazeliskとLLVMをインストールします。Macの人は`export PATH="$(brew --prefix llvm)/bin:${PATH}"`も必要だそうです。

```bash
brew install bazelisk
brew install llvm
```

bazeliskとはGoogleの作ったビルドツールで、いわばmakeみたいなものらしいです。

### ビルドして実行してみる

適当な場所でcarbon-langプロジェクトをgit cloneして、ビルドを実行します。

```
git clone https://github.com/carbon-language/carbon-lang
cd carbon-lang

bazel run //explorer -- ./explorer/testdata/print/format_only.carbon
```

ビルドのログが流れた後、"Hello World!"と表示されました。
![2022-07-24_00h33_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728326/14974ee8-1bdc-437c-d9b9-97431aef6d66.png)
bazelの使い方がいまひとつ分かりませんが、`//explorer`という名前の環境で[format_only.carbon](https://github.com/carbon-language/carbon-lang/blob/trunk/explorer/testdata/print/format_only.carbon)を実行しているようです。



## FizzBuzzを実行してみる

Hello Worldしたので、簡単なサンプルプログラムとしてFizzBuzzを実行してみます。数字を数え上げていき、3の倍数はFizzと表示し、5の倍数はBuzzと表示し、どちらも当てはまる場合はFizzBuzzと表示するやつです。

適当な場所にファイルを作って次のコードを書きます。

```rust:FizzBuzz_NG.carbon
package FizzBuzz api;

fn Main() -> i32 {
    var i: i32 = 1;
    while (i < 100) {
        var f: bool = i % 3 == 0;
        var b: bool = i % 5 == 0;
        if (f && b) {
            Print("FizzBuzz");
        } else if (f) {
            Print("Fizz");
        } else if (b) {
            Print("Buzz");
        } else {
            Print("{0}", i);
        }

        i = i + 1;
    }

    return 0;
}
```

次のように実行します。Hello Worldと同様に`bazel run //explorer -- /path/to/FizzBuzz_NG.carbon`でも良いのですが、これでもできました [^5]

```bash
cd /path/to/carbon-lang # git cloneしたディレクトリをcdしておく
./bazel-bin/explorer/explorer /path/to/FizzBuzz_NG.carbon # 
```

ファイル名がネタバレ気味でしたがエラーです。`\x3C`つまり5行目の不等号`<`がだめだそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728326/951f38c1-4f14-1e9e-805e-8b289edb3910.png)
これ以外にも`f32`型、剰余演算子`%`、日本語文字列などが使えませんでした。まだ実験段階、しかも数日前に公開されたばかりなので仕方ありません。

`%`や`<`を使えないのはFizzBuzzで致命的ですが、幸い`if`や`==`は使えたので頑張ってFizzBuzzしてみます。

```rust:FizzBuzz.carbon
package FizzBuzz api;

fn Main() -> i32 {
    var i: i32 = 1;
    var f: i32 = 3; // 3の倍数フラグ、1のとき3の倍数
    var b: i32 = 5; // 5の倍数フラグ、1のとき5の倍数
    while (true) {
        if (i == 100) {
            break;
        }

        if (f * b == 1) {
            Print("FizzBuzz");
        } else if (f == 1) {
            Print("Fizz");
        } else if (b == 1) {
            Print("Buzz");
        } else {
            Print("{0}", i);
        }

        i = i + 1; 
        f = if f == 1 then 3 else f - 1;
        b = if b == 1 then 5 else b - 1;
    }

    return 0;
}
```

あまりスマートなコードではありませんが、実行してみるとうまくいきました。満足です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2728326/f06c7608-95e0-3697-294b-b3277f9534d4.png)
文法については、Hello Worldのコードと同じ[explorerのテストコード](https://github.com/carbon-language/carbon-lang/tree/trunk/explorer/testdata)や[言語設計のドキュメント](https://github.com/carbon-language/carbon-lang/tree/trunk/docs/design)を見るとなんとなく分かります。例えば`&&`が使えないと思ったら`and`で書けばよかったりしたので、コードを書いてみる前に目を通すと良さそうです。



## あとがき・雑感

Carbonの立ち位置を考えると私は今後使う機会があるとは思わないのですが、遊びがてら最新のプログラミング言語を試してみました。

Rustが人気な理由の一因はCargoにあるイメージがあります<sup>[要出典]</sup>が、Carbonもツールチェインを頑張るそうです。ひょっとしたら数年後にはC++やRustと並んでCarbonが選択肢に並ぶ未来があるのでしょうか

[^1]: https://carbon.nesbot.com/docs/
[^2]: https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/faq.md#if-you-can-use-rust-ignore-carbon
[^3]: ちなみに[このページ](https://github.com/carbon-language/carbon-lang/blob/trunk/docs/project/contribution_tools.md#:~:text=TODO%3A%20We%27d%20like%20to%20use%20apt%2C%20but%20standard%20LLVM%20Debian%20packages%20are%20not%20configured%20correctly%20for%20our%20needs.%20We%20are%20currently%20aware%20of%20two%20libc%2B%2B%20issues%2C%2043604%20and%2046321.)によると「本来ならaptを使いたいが、DebianのLLVMには不具合があってしょうがなくbrewにしている」とのことです
[^4]: FizzBuzz_NG.carbonのようにコンパイルエラーになったときも"Build completed successfully"と出て、それとは別に"COMPILATION ERROR:"が表示されます。察するに、実行環境（Carbon Explorer）自体のビルドが通ったということっぽいです
[^5]: 講演でのCarbon Explorerのデモを真似ただけです https://youtu.be/omrY53kbVoA?t=2244