Tech Racho エンジニアの「?」を「!」に。
  • 開発

V言語: Goのようにシンプルで、Rustのように小さいバイナリ

こんにちは、hachi8833です。昨年夏に話題になったV言語を半年遅れで知って最近遊んでいます。「主観的には」かなり安定して動く印象です。

なお以下のベンチマークは、そういう結果もあるのねというぐらいに思っていただければと☺️。

V言語そのものについてはQiitaに半年前のドキュメントの和訳があるのでそちらをどうぞ。READMEのインストール方法も「さほど」難しくありません。

「コード例で学ぶV言語」

V言語を追いかけながら、v-community/v_by_exampleを日本語版に翻訳いたしました。マージありがとうございます!

ざっくり特徴

1. 主にGo言語の影響を強く受けているコンパイラ言語

V言語は当初Go言語で記述されたこともあり、Go言語の特徴の多くを取り入れています(強い型、クラスがない、ループはforのみ、言語レベルのlint、クロスプラットフォーム、goroutineなど)。

現在はC言語固有の部分をごくわずか残している他はほぼすべてV言語自身で記述されていて、Goのコードは残っていません。

Go言語を知ってる人にはとりあえず以下のWikiが参考になると思います。

参考: V for Go developers · vlang/v Wiki

その一方、作者のmedvednikovさんもREADMEにopinionated(独断と偏見の)と記載しているように、Go言語で彼が気に入らなかったであろうと思われる仕様や、Go言語では今更変えられなさそうな仕様をいろいろ変更しています。

特に、変数がデフォルトでイミュータブルかつprivate(変えるにはmutpubを明示的に指定する必要がある)というあたりは好き嫌いが分かれそうなところです。私はpublicみたいな長ったらしいアクセス指定子よりは好きです❤️。

表記における記号への依存が少なめなところは、どことなくPythonのようでもあります(Pythonの影響については明言されていませんが)。

デフォルトでイミュータブルではありますが、V言語は純粋な関数型言語ではないとのことです。しかし関数型言語からもいくつかアイデアを取り入れていて、個人的にor { }でエラーハンドリングできるところが好きです(Goにこれ欲しい…😢)。

fn main() {
    repo := new_repo()
    // Option 型は`or`ブロックで扱わなければならない
    user := repo.find_user_by_id(10) or {
        return  // `or`ブロックの末尾は`return`か`break`か`continue`でなければならない
    }
    println(user.id) // "10" 
    println(user.name) // "Charles"
}

追記(2020/03/19): ジェネリクスはGoで長らく「不要」とされ、現在ドラフト段階↓ですが、V言語ではそのジェネリクスも導入されているようです。ああ、これがやりたかったのかなと想像しています。情報が少ないのと、自分がジェネリクスにあまり興味がないこともあって今ひとつわかりませんが。

参考: Go 2のgenerics/contract簡易まとめ - Qiita

# docs.mdより
struct Repo<T> {
    db DB
}

fn new_repo<T>(db DB) Repo<T> {
    return Repo<T>{db: db}
}

// This is a generic function. V will generate it for every type it's used with.
fn (r Repo<T>) find_by_id(id int) ?T {
    table_name := T.name // in this example getting the name of the type gives us the table name
    return r.db.query_one<T>('select * from $table_name where id = ?', id)
}

db := new_db()
users_repo := new_repo<User>(db)
posts_repo := new_repo<Post>(db)
user := users_repo.find_by_id(1)?
post := posts_repo.find_by_id(1)?

2. コンパイルが高速、バイナリが小さい

この業界では、速いという言葉はそれだけで耳目を集めがちです。V言語は、少なくともセルフコンパイルは1秒かからず、驚くほど高速です。

コンパイルしてできたバイナリの実行速度は真面目に調べていませんが、まだ最適化を頑張る段階ではないので改良の余地はありそうな雰囲気です。バイナリ実行速度ではGoよりまだ遅いものもあるようです。

Go言語と同じく、デフォルトではワンバイナリになります。オプションを指定することでvlib/を切り離せるので、IoTやOSといった用途も視野に入っています。

Go言語のバイナリはGC(ガベージコレクション)などの機能を内蔵しているので、Hello worldレベルのソースでもコンパイルすると数MBになってしまいますが、V言語はRust的な「GCを使わない」設計を採用していて、vlibが急成長しているVコンパイラ自体のバイナリサイズは1MB未満です。他にもOberonやSwiftなどの影響を受けているそうですが、どこがそうなのか私にはわかりません。

-rwxr-xr-x 1 hachi8833 staff 840K  2 14 14:03 /Users/hachi8833/deve/vlang/v_mac/v

現在でもlibcなどのc言語ライブラリへの依存は少ないのですが、最終的にはlibcなどのライブラリへの依存も完全になくすつもりのようです。

なお現状のV言語はCへのトランスパイラなのでCのコンパイラが必要です。その一方で「いつでもCのコードを生成できる」ことを目標にしているとのことなので、今後ネイティブコンパイルが実現されてもCコードの生成はできるようにしておくそうです。その気になればC経由でWeb Assemblyをビルドすることもできそうですね。

参考: C/C++からWebAssemblyにコンパイルする - WebAssembly | MDN

3. クロスプラットフォームのGUIライブラリ

V言語はもともとVoltというSNSクライアントアプリを書くために作られた言語とのことです(Voltという別の言語もあるのでややこしい😅)。そのためかクロスプラットフォームのGUIライブラリv/uiを最初から備えています。

tcl/tkのようなレガシー感20世紀感とは無縁な、今どきらしいGUIなのがうれしいですね😋。

4. 驚異的な開発速度、活発なコミュニティ

V言語の様子を知るにはDiscordを覗いてみるとよいでしょう。土日祝日盆暮れ正月おかまいなしで盛り上がっています。

何しろ発展途上ですので細かいバグつぶしはたくさんあります。近々0.2をリリースする意向のようです。コアメンバーたちが絶えずissueをつぶしていますが、issueもそれを上回る勢いで増えてます。

しかも0.2ではこの期に及んで、今後のメンテをやりやすくするためにVのパーサーをASTベースで完全に書き直すという作業を今年2月の数週間で終えてしまいました😳。道理でパーサーが2つあるわけだ。

目についた課題

以下は記事執筆時点のものです。

1. ドキュメントのキャッチアップ

ドキュメント(docs.md)に載っていない情報がまだあり、最終的にはコミットやソースコメントあたりが頼りです。

特にシンタックスの制約に関する記述がまだ不足しています。

  • 関数名: スネークケースしか許されない(fooはいいがFooはだめ)
  • 変数名: スネークケースしか許されない
  • インターフェース名: PascalCaseしか許されない(CommonDelegatorのような名前)
    • 現在はerで終わる名前しか使えないという制約も課されているが、外される予定とのこと

まだまだ動きが激しいので、しばらく静観することにします。

2. 仕様ファーストではなさそう

これまでV言語を追いかけた限りでは、最初に仕様を固めてから実装するというより、実装先行で仕様が後追いっぽいように見えます(違ってたらすみません)。

何しろ強い人たちなので、ちまちま仕様を書くよりはとにかくエイヤで実装というノリなのかなと思えました。現実にはこうやってできていく言語も多いのでしょう。

しかし現在激しく実装中のv fmtのあたりとかは仕様が頭に入ってる人たちでないと手出しが難しそうですし、どちらかというと緩めのASTの挙動をとりあえずv fmtで無理やり引き締めているような気もします。自分は仕様が気になるたちなので、早いところ仕様が固まってくれるとうれしいです。

3. サードパーティパッケージの安定性

Vで書かれたコードのうち、VそのものとvlibのVコードのみを使うCLIアプリは概ね安定している印象ですが、既存のCライブラリ(JSONやGUIなど)にリンクするアプリには安定してないものもあるようです。

特に、macOSのreadlineはまだ機能が少なく、Linux版ではできているコマンドラインでのショートカット(Ctrl-aで冒頭に移動、Ctrl-eで末尾に移動など)やで履歴を遡る機能が今のところ使えません😭。

少なくともmacOSでサードパーティのコードをビルドするには、Command Line Toolsをインストールしておく必要があります。古い場合はアップグレードも必要です。Command Line Toolsのインストール方法はちょくちょく変わるので面倒…😢。

参考: macOSでcommand line tools for xcodeとhomebrewのインストール - Qiita

最後に

V言語は発展途上段階なので、今のところ「ただちに何かの業務に役立つ」ものではないと思いますが、言語が急速に成長していく姿をつぶさに観察しているときのライブ感・臨場感が楽しくてたまりません😋。

この調子で順調に成長してくれれば、Go言語に似ている分、Go言語の得意なミドルウェアやCLIでの利用が考えられますし、Goがあまり視野に入れていないクロスプラットフォームGUIアプリも期待できます。バイナリが小さいので、Go言語があまり視野に入れていないOS開発やインタプリタ言語の開発にも使えそうです。気の早い人たちはV言語でOSを書き始めています。

関連記事

Goby: Rubyライクな言語(2)Goby言語の全貌を一発で理解できる解説スライドを公開しました!


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。