Last active
July 3, 2022 12:31
-
-
Save eggplants/5d9b0e83ff4ad4025706e7a5b0080a4d to your computer and use it in GitHub Desktop.
Learn Nim in 5 minutes ( https://learnxinyminutes.com/docs/nim , accessed-at: 2022-06-26) の日本語訳
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 一行だけのコメントは `#` から始まります。 | |
#[ | |
これは複数行のコメントです。 | |
Nimでは、複数行のコメントはネスト可能で、#[ に始まり | |
... ]# に終わります。 | |
]# | |
discard """ | |
これでも複数行のコメントとして機能します。 | |
正しくパースできない、壊れたコードに使うと良いです。 | |
""" | |
var # 変数の宣言や代入時には、 | |
letter: char = 'n' # 型注釈があってもなくても良いです。 | |
lang = "N" & "im" | |
nLength: int = len(lang) | |
boat: float | |
truth: bool = false | |
let # 一度きりの宣言や代入の際には let を使いましょう。 | |
legs = 400 # 👈の変数 `legs` は不変(immutable, 再代入が不可能)です。 | |
arms = 2_000 # 数字内の `_` は無視されます。でかい数字を書くのに便利です。 | |
aboutPi = 3.15 | |
const # 定数はコンパイル時に計算されます。 | |
debug = true # これはコンパイル時定数(C++のconstexpr文)として便利な特性を発揮します。 | |
compileBadCode = false | |
when compileBadCode: # `when` はいわゆるコンパイル時 `if` (C++のconstexpr if文) です。 | |
legs = legs + 1 # 👈は誤ったコードですが、絶対にコンパイルされることはないです。 | |
const input = readline(stdin) # Const 変数はコンパイル時に値がわかってないといけません。 | |
discard 1 > 2 # ⚠Nimのコンパイラは式の結果がどこからも使われないままだとキレます。 | |
# `discard` で無視できます。 | |
# | |
# データ構造 | |
# | |
# タプル (tuple) | |
var | |
child: tuple[name: string, age: int] # タプルはフィールド名と順序の両方を持ちます。 | |
today: tuple[sun: string, temp: float] | |
child = (name: "Rudiger", age: 2) # 代入は `()` リテラルか個別のフィールドを使って | |
today.sun = "Overcast" # 一度だけ行えます。 | |
today.temp = 70.1 | |
# シーケンス (seq) | |
var | |
drinks: seq[string] | |
drinks = @["Water", "Juice", "Chocolate"] # `@[値1,..,値n]` はシーケンスリテラルになります。 | |
drinks.add("Milk") | |
if "Milk" in drinks: | |
echo "We have Milk and ", drinks.len - 1, " other drinks" | |
let myDrink = drinks[2] | |
# | |
# 型を定義してみる | |
# | |
# 自分で型を定義して、コンパイラに仕事をさせてみましょう。 | |
# 静的片付けを強力かつ扱いやすいものにできます。 | |
type | |
Name = string # 型エイリアスは元の型と相互変更可能だけど、 | |
Age = int # よりわかりやすい (descriptive) 新たな型をあなたにもたらします。 | |
Person = tuple[name: Name, age: Age] # データ構造も定義できます。 | |
AnotherSyntax = tuple | |
fieldOne: string | |
secondField: int | |
var | |
john: Person = (name: "John B.", age: 17) | |
newage: int = 18 # `int` 型より `Age` 型の方がいいのですが… | |
john.age = newage # まだこれでも動きます。 `int` 型は `Age` 型の同意語 (synonym) ですからね。 | |
type | |
Cash = distinct int # `distinct` で、新しい型を元の型と | |
Desc = distinct string # 「不適合なもの」として宣言できます。 | |
var | |
money: Cash = 100.Cash # `.Cash` で `int` 型のものをユーザ定義の型(ここでは `Cash`型)にできます。 | |
description: Desc = "Interesting".Desc | |
when compileBadCode: | |
john.age = money # !エラー! `age` は `int` 型で `money` は `Cash` 型です。 | |
john.name = description # コンパイラくん「ありえんだろ!」 | |
# | |
# もっと!型とデータ構造 | |
# | |
# 列挙型 `enum` は、限られた数の値のうちの1つだけを持てます。 | |
type | |
Color = enum cRed, cBlue, cGreen | |
Direction = enum # もう一つの書き方 | |
dNorth | |
dWest | |
dEast | |
dSouth | |
var | |
pixel = cGreen # `pixel` は `Color` 型であり、 `cGreen` 型を持っています。 | |
orient = dNorth # `orient` は `Direction` 型であり、`dNorth` 型を持っています。 | |
discard dNorth > dEast # `enum` 型は普通、順序型(ordinal type)です。 | |
# 部分範囲型 `range[下限..上限]` は、 有効範囲を限定して指定できます。 | |
type | |
DieFaces = range[1..20] # 有効な値は1〜20の `int` 型だけです。 | |
var | |
my_roll: DieFaces = 13 | |
when compileBadCode: | |
my_roll = 23 # !エラー! | |
# 配列 は `array[添字の型, 要素の型]` で宣言できます。 | |
type | |
RollCounter = array[DieFaces, int] # `array` 型のものは可変長で、 | |
DirNames = array[Direction, string] # 順序型ならどんなものでも添字にできます。 | |
Truths = array[42..44, bool] | |
var | |
counter: RollCounter | |
directions: DirNames | |
possible: Truths | |
possible = [false, false, false] # [値1,..,値n]でリテラル配列を作成できます。 | |
possible[42] = true | |
directions[dNorth] = "Ahh. The Great White North!" | |
directions[dWest] = "No, don't go there." | |
my_roll = 13 | |
counter[my_roll] += 1 | |
counter[my_roll] += 1 | |
var anotherArray = ["Default index", "starts at", "0"] | |
# これらの他にも利用可能なデータ構造があります。 | |
# テーブル (tables) 、 集合 (sets) 、 リスト (lists) 、キュー (queues) 、基数木 (crit bit trees) ... | |
# 詳細👉 http://nim-lang.org/docs/lib.html#collections-and-algorithms | |
# | |
# 入出力と制御構文 | |
# | |
# `case` + `readLine()` | |
echo "Read any good books lately?" | |
case readLine(stdin) | |
of "no", "No": | |
echo "Go to your local library." | |
of "yes", "Yes": | |
echo "Carry on, then." | |
else: | |
echo "That's great; I assume." | |
# `while` + `if` + `continue` + `break` | |
import strutils as str # 詳細👉 http://nim-lang.org/docs/strutils.html | |
echo "I'm thinking of a number between 41 and 43. Guess which!" | |
let number: int = 42 | |
var | |
raw_guess: string | |
guess: int | |
while guess != number: | |
raw_guess = readLine(stdin) | |
if raw_guess == "": continue # 現在の繰り返しを飛ばす | |
guess = str.parseInt(raw_guess) | |
if guess == 1001: | |
echo("AAAAAAGGG!") | |
break | |
elif guess > number: | |
echo("Nope. Too high.") | |
elif guess < number: | |
echo(guess, " is too low") | |
else: | |
echo("Yeeeeeehaw!") | |
# | |
# 反復 (Iteration) | |
# | |
for i, elem in ["Yes", "No", "Maybe so"]: # 単に `for elem in` でもOK | |
echo(elem, " is at index: ", i) | |
for k, v in items(@[(person: "You", power: 100), (person: "Me", power: 9000)]): | |
echo v | |
let myString = """ | |
an <example> | |
`string` to | |
play with | |
""" # 複数行の raw 文字列 | |
for line in splitLines(myString): | |
echo(line) | |
for i, c in myString: # それぞれ添字と文字をとりだす。文字だけなら `for j in` でOK | |
if i mod 2 == 0: continue # `if` のコンパクトな書き方 | |
elif c == 'X': break | |
else: echo(c) | |
# | |
# プロシージャ (Procedures, 一般複数の処理を一つの関数に固めたもの) | |
# | |
type Answer = enum aYes, aNo | |
proc ask(question: string): Answer = | |
echo(question, " (y/n)") | |
while true: | |
case readLine(stdin) | |
of "y", "Y", "yes", "Yes": | |
return Answer.aYes # `Enum` 型で値の型を限定できます。 | |
of "n", "N", "no", "No": | |
return Answer.aNo | |
else: echo("Please be clear: yes or no") | |
proc addSugar(amount: int = 2) = # 引数 `amount` の デフォルト値は 2で、返り値はありません。 | |
assert(amount > 0 and amount < 9000, "Crazy Sugar") | |
for a in 1..amount: | |
echo(a, " sugar...") | |
case ask("Would you like sugar in your tea?") | |
of aYes: | |
addSugar(3) | |
of aNo: | |
echo "Oh do take a little!" | |
addSugar() | |
# ここで `else` 節は必要ありません。`yes` か `no` だけが可能です。 | |
# | |
# FFI (Foreign function interface、他言語の関数を呼び出す機能) | |
# | |
# Nim は C言語にコンパイルされるため、FFIは容易です。 | |
proc strcmp(a, b: cstring): cint {.importc: "strcmp", nodecl.} | |
let cmp = strcmp("C?", "Easy!") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment