本家様
ここからの抜粋&翻訳
Luaとの違いがある場合はそちらも併記します.
ざっくりと簡単な部分だけ導入しておきます.
プリミティブ
bool, string型はLuaと変わりありません.
数値型
local dec = 1234 -- variable of type 'integer'
local bin = 0b1010 -- variable of type 'uint8', set from binary number
local hex = 0xff -- variable of type 'integer', set from hexadecimal number
local char = 'A'_u8 -- variable of type 'uint8' set from ASCII character
local exp = 1.2e-100 -- variable of type 'number' set using scientific notation
local frac = 1.41 -- variable of type 'number'
print(dec,bin,hex,char,exp,frac)
local pi = 0x1.921FB54442D18p+1 -- hexadecimal with fractional and exponent
print(pi) -- outputs: 3.1415926535898
local a = 1234_u32 -- variable of type 'int32'
local b = 1_f32 -- variable of type 'float32'
local c = -1_isize -- variable of type `isize`
print(a,b,c) --outputs: 1234 1.0 -1
バイナリー型,アスキー文字形式への対応のほか,サフィックスで型を指定できるようになりました
配列
local a: [4]integer = {1,2,3,4}
print(a[0], a[1], a[2], a[3]) -- outputs: 1 2 3 4
local b: [4]integer
print(b[0], b[1], b[2], b[3]) -- outputs: 0 0 0 0
local len = #b -- get the length of the array, should be 4
print(len) -- outputs: 4
コンパイル時に配列のサイズを確定させることができるようになったのは大きいです.また,配列のサイズは指定しなくとも推論されます.
列挙型
require 'traits'
local Weeks = @enum{
Sunday = 0,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
print(Weeks.Sunday) -- outputs: 0
local a: Weeks = Weeks.Monday
print(a) -- outputs: 1
print(type(a)) -- outputs: number
switch同様実装された模様.とはいえtostringもtypeにも対応していないのは何も変わっていないように見える.自作Enumなどなくとも,型注釈含め,コードの可読性向上に貢献してくれるかどうかといったところ.
レコード型
local Person = @record{
name: string,
age: integer
}
-- typed initialization
local a: Person = {name = "Mark", age = 20}
print(a.name, a.age)
-- casting initialization
local b = (@Person){name = "Paul", age = 21}
print(b.name, b.age)
-- ordered fields initialization
local c = (@Person){"Eric", 21}
print(c.name, c.age)
-- late initialization
local d: Person
d.name = "John"
d.age = 22
print(d.name, d.age)
Luaではテーブル型に強引に要素を追加する形で表現されていた.@recordキーワードがなければエラーになるほか,typeはrecordと判定される.
ユニオン型
local IntOrFloat = @union{
i: int64,
f: float64,
}
local u: IntOrFloat = {i=1}
print(u.i) -- outputs: 1
u.f = 1
print(u.f) -- outputs: 1.0f
print(u.i) -- outputs some garbage integer
新規構文.Cでの共用型に相当し,上記コードから分かるように,Unionの中で有効な値は一つのみで,それ以外はGCによって回収されている
ポインター
local n = nilptr -- a generic pointer, initialized to nilptr
local p: pointer -- a generic pointer to anything, initialized to nilptr
local i: *integer -- pointer to an integer
local a: integer = 10
i = &a
print(i) -- 適当なメモリの値
新規構文.もともとのLuaの用途的にポインタが必要になる場面がそんなにあるのか?
関数ポインタ
local function add_impl(x: integer, y: integer): integer
return x + y
end
local function double_add_impl(x: integer, y: integer): integer
return 2*(x + y)
end
local add: function(x: integer, y: integer): integer
add = add_impl
print(add(1,2)) -- outputs 3
add = double_add_impl
print(add(1,2)) -- outputs 6
Luaでも元からできていたことではあるが,特に型注釈をつけられるようになった恩恵が大きい.
Type型
local MyInt: type = @integer -- a symbol of type 'type' holding the type 'integer'
local a: MyInt -- variable of type 'MyInt' (actually an 'integer')
print(a) -- outputs: 0
いわゆるエイリアス.
明示的な型変換
local i = 1
local f = (@number)(i) -- convert 'i' to the type 'number'
print(i, f) -- outputs: 1 1.0
local MyNumber = @number
local i = 1
local f = MyNumber(i) -- convert 'i' to the type 'number'
print(i, f) -- outputs: 1 1.0
local ni: integer = -1
-- the following would crash with "narrow casting from int64 to uint64 failed"
--local nu: uinteger = ni
local nu: uinteger = (@uinteger)(ni) -- explicit cast works, no checks are done
print(nu) -- outputs: 18446744073709551615
オペレーター
以下のオペレーターが追加されました.
-
///
%%%
: 商を0に丸めます. -
>>>
: 算術右シフトを計算します. -
$
: メモリが参照している値を出します. -
&
: メモリを参照します.
関数
戻り値の推論
local function add(a: integer, b: integer)
return a + b -- return is of deduced type 'integer'
end
print(add(1, 2)) -- outputs
再帰関数の場合は,戻り値の推論ができないので明示的に指定する必要があります.
複数の戻り値
local function get_multiple(): (boolean, integer)
return false, 1
end
local a, b = get_multiple()
print(a,b) -- outputs: false 1
無名関数
local z = function(x: integer):integer return x + 10 end
print(z(10))
型注釈がつけられるようになった
ポリモーフィック関数
local function add(a: auto, b: auto)
return a + b
end
local a = add(1,2)
-- call to 'add', a function 'add(a: integer, b: integer): integer' is defined
print(a) -- outputs: 3
local b = add(1.0, 2.0)
-- call to 'add' with different types, function 'add(a: number, b: number): number' is defined
print(b) -- outputs: 3.0
print(add(1, 'b')) -- compile time error!
+オペレーターに対応しない値を渡してもコンパイルエラーにはならず,ランタイムで落ちます.プリプロセッサーを使用することでそれを防ぐことができます.
local function preprocess_add(a: auto, b:auto)
## static_assert(a.type.is_scalar, 'a is not a number. type "%s"', a.type)
## static_assert(b.type.is_scalar, 'b is not a number. type "%s"', b.type)
return a + b
end
詳しくは Concepts へ
レコード型の関数
local Vec2 = @record{x: number, y: number}
function Vec2.create(x: integer, y: integer): Vec2
return (@Vec2){x, y}
end
local v = Vec2.create(1,2)
print(v.x, v.y) -- outputs: 1.0 2.0
local Rect = @record{x: number, y: number, w: number, h: number}
function Rect:translate(x: number, y: number)
-- 'self' here is of the type '*Rect'
self.x = self.x + x
self.y = self.y + y
end
function Rect:area()
-- 'self' here is of the type '*Rect'
return self.w * self.h
end
local v = Rect{0,0,2,3}
v:translate(2,2)
print(v.x, v.y) -- outputs: 2.0 2.0
print(v:area()) -- outputs: 6.0
examples/record_inheretance.nelua が詳しい