V言語メモ

# V言語メモ

コンパイル爆速が売りの[V言語](https://vlang.io/)をざっと触ってみたので、気に入った点や、ドキュメントには書かれていない使い方をメモっておきます。バージョンはV 0.1.8です。

# 変数定義

宣言は:=で、代入は=で行うgolang風のスタイル。

変数はデフォルトが Immutableなので、変数を変更する箇所があるとコンパイルが通りません。変更が必要な変数はmutをつけて宣言する必要があります。このあたりはRustから来てるんでしょうかね。

```
a:=10
a=20 // NG

mut b:=10
b=20 // OK
```

# 標準入出力

printlnは実装をみると結局C言語のprintfだったりしますが、細かいところが便利になっています。import類がいらないのもいいですね。配列とかを渡してもいいかんじに表示してくれて、スクリプト言語感覚で使えます。

文字列置き換えが簡単。rubyっぽい。

```
i:=99
println(i)
println('$i is the number')
```

formatは下記のように書けるようです。

```
i:=99
println('${i:04d}')
```

コマンドライン引数は下記のように文字列のArrayとして取れます。python的。

```
import os

fn main() {
    println(os.args)
}
```


# Array

python でいうenumerateが標準装備。これすごくいい。。

```
mat:=[10,20,30]
for x in mat{
    println(x)
}
for i,x in mat{
    println('$i : $x')
}
```

forループ内はread onlyなので、内容を書きかえたい場合は
indexで指定するべしとのこと。

```
mat:=[10,20,30]
for i,x in mat{
    println(x)
    mat[i] *=10
}
```

空の配列をつくって内容を積んでいく処理は下記のように書けます。
for文はC言語のwhile相当ですかね、初期化と更新は勝手にやれというスタイル。

```
mut ary:=[]int

mut i:=0
for i<10 {
    ary << i
    i++
}

println(ary)
```



# クラス

クラスのかわりに、メソッドつきStructみたいなものを作れるようです。Rustでいうtraitを定義せずいきなりメソッド実装するようなイメージでしょうか。

C++の下記のようなコード：

```C++
#include <iostream>
using namespace std;

class Hoge{
    private:
        string name;
    public:
        Hoge(string theName){name=theName;}
        void hello();
};

void Hoge::hello(){
    cout << "Hello, " << name << "!" <<endl;
}

int main(){
    Hoge h("hogehoge");
    h.hello();
}
```

をVで置き換えると、下記のようになります。だいぶスッキリ書けますね。

```V
struct Hoge{
    name string
}

fn (h Hoge) hello() {
    println('Hello, ${h.name}!')
}

fn main() {
    h := Hoge{'hogehoge'}
    h.hello()
}
```

断りない限りImmutableという前提はここでも貫かれていて、内容を書き換えたい場合は、structのインスタンスなりメンバ変数なりがmutになっていないといけません。たとえば以下のとおり。


```V
struct Hoge{
    mut: name string
}

fn (h mut Hoge) change_name(the_name string) {
    h.name=the_name
}

fn (h Hoge) hello() {
    println('Hello, ${h.name}!')
}

fn main() {
    mut h := Hoge{'hogehoge'}
    h.change_name('hugahuga')
    h.hello()
}
```

mutまみれでたいそう美しくないので、自ずとこういう実装は避けるようになるでしょう。

# C/C++ Translator

現時点ではまだ使えないそうです。残念。

# C言語呼び出し

```test_clib.c

int c_add(int a,int b){
    return a + b;
}
```

```test_clib.h
#ifndef TEST_CLIB_H
#define TEST_CLIB_H
int c_add(int a,int b);
#endif
```

というCライブラリを作り、下記のようにV言語から呼びます。リンクオプション等をpragmaっぽく記述してますね。

```test_extc.v
#flag -ltest_clib -L.
#include "test_clib.h"

fn main() {
    a := int(C.c_add(10,20))
    println(a)
}
```

ビルドは下記のように行います。

```
gcc -shared test_clib.c -o libtest_clib.so
v test_extc.v
```

# 画面描画

サンプルの[テトリス](https://github.com/vlang/v/tree/master/examples/tetris)が参考になります。

- gg　（描画ライブラリ。SDLみたいなのをめざしてるのかな？）
- gx　(描画要素のライブラリ)
- gl　(gladのラッパ)
- glfw　(GLFW3のラッパ)

という構成で動作しているようです。このあたりは今後ガンガン書き換わる気配がします。

見よう見まねでボールが跳ねるデモを作ってみました。コードは[こちら](https://github.com/ashitani/v_lang_examples)においておきます。
コード等はgithubを参照ください。DOOMがビルドできているというだけあって、ゲーム類はわりとさっくり作れそうですね。

![balls_movie.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30340/8e3e2081-03f9-69f5-8395-d5929d289535.gif)


# まとめ

外部ライブラリの類は現時点ではCライブラリの流用が多いみたいですが、コンパイルを速くするための工夫があちこちに見えます。

表記の冗長性を減らす、関数内での参照は極力少なくする、極力mutを使わない、等々ですが、その結果使い勝手が劇的に下がるわけでもなく、結果的にキータイプやバグも減ったりして、プログラマにとっても嬉しい方向性な気がします。

マニュアルにない内容でも、「この書き方は通るかな？」と書いてみるとだいたい通るので、ストレスが少ないです。コードも追いやすいですね。トータルではとても手に馴染む言語という感想です。