はじめに
構文の確認程度に書いてみた。
元はNimで書いたライフゲーム用の簡易モジュールをV言語で書き直しただけ。
https://github.com/jiro4989/gameoflife
開発環境
- V 0.1.11
- Linux Mint 19.1
コード
import time
const (
dead = 0
live = 1
)
fn get_neighbour_cells(board [][]int, x, y int) []int {
mut result := []int
for y2 := y-1; y2 <= y+1; y2++ {
if y2 < 0 || board.len <= y2 {
continue
}
for x2 := x-1; x2 <= x+1; x2++ {
if x2 < 0 || board[y2].len <= x2 {
continue
}
if x == x2 && y == y2 {
continue
}
result << board[y2][x2]
}
}
return result
}
fn is_reproduction(self, living_cell_count int) bool {
if self != dead {
return false
}
return living_cell_count == 3
}
fn is_generation(self, living_cell_count int) bool {
if self != live {
return false
}
return living_cell_count == 2 || living_cell_count == 3
}
fn is_underpopulation(self, living_cell_count int) bool {
if self != live {
return false
}
return living_cell_count <= 1
}
fn is_overpopulation(self, living_cell_count int) bool {
if self != live {
return false
}
return 4 <= living_cell_count
}
fn next_step(board [][]int) [][]int {
// v0.1.11
// この構文はまだ使えないみたい
// mut new_board := [][]int
// 今は多次元配列をこう定義する
mut new_board := []array_int
for y := 0; y < board.len; y++ {
row := board[y]
mut new_row := []int
for x := 0; x < row.len; x++ {
cell := row[x]
nc := get_neighbour_cells(board, x, y)
mut living_cell_count := 0
for c in nc {
if c == live {
living_cell_count++
}
}
if cell == dead {
if is_reproduction(cell, living_cell_count) {
new_row << live
} else {
new_row << dead
}
continue
}
if is_generation(cell, living_cell_count) {
new_row << live
} else if is_underpopulation(cell, living_cell_count) {
new_row << dead
} else if is_overpopulation(cell, living_cell_count) {
new_row << dead
}
}
new_board << new_row
}
return new_board
}
fn print_board(board [][]int) {
for row in board {
mut s := '|'
for c in row {
s += ' $c |'
}
println(s)
}
}
//////////////////////////////////////////////////
// メイン処理
//////////////////////////////////////////////////
mut board := [
[dead, dead, dead, dead, dead],
[dead, dead, dead, dead, dead],
[dead, live, live, live, dead],
[dead, dead, dead, dead, dead],
[dead, dead, dead, dead, dead],
]
for {
board = next_step(board)
print_board(board)
println('------------------------------')
time.sleep(1)
}
実行方法
公式リポジトリからmakeしてPATH通して動かしました。
git clone https://github.com/vlang/v.git
cd v
make
sudo cp -p v /usr/local/bin
cd ..
v run gameoflife.v
感想
構文はGoととても似ているけれど要所要所が違う。
今回書いてみたコードだけでもこれだけ違うことに気づいた。
- 変数宣言が
mut 変数名 := 値。mutつけないと値を変更できない。 - 配列の長さの取得が
array.len - 文字列リテラルにシングルクォートを使う
- 文字列内で変数展開ができる
$variable_name - 命名規則がlower_snake_case
- 値ループが
for value in elements - 関数宣言が
fn - 配列宣言にいきなり
[1, 2, 3]と書ける - 空配列の宣言が
mut array := []type_name - 配列の末尾要素追加が
array << item
構文だけみたらGoより多少簡単に書けるように変更が入ってるのかな、くらい。
標準ライブラリを読んだ感じTODOも多いしコンパイラ自体にバグも多い。
始まったばかりですし今後どう変わっていくかに期待します。
ちなみに、ネストしたマルチラインコメントに対応してなかったので、バグ修正のPR投げたりしました。
https://github.com/vlang/v/pull/917
(公式ドキュメントではネストしたコメントOKとか書いてあったはずなのになぜ対応してなかったのか)