型自動キャスト¶
Crystalは、曖昧さが無い場合、特定の型の要素を透過的にキャストします。
数値の自動キャスト¶
数値型の値は、精度が失われない場合、より大きな型に自動キャストされます。
def foo(x : Int32) : Int32
x
end
def bar(x : Float32) : Float32
x
end
def bar64(x : Float64) : Float64
x
end
foo 0xFFFF_u16 # OK, an UInt16 always fit an Int32
foo 0xFFFF_u64 # OK, this particular UInt64 fit in an Int32
bar(foo 1) # Fails, casting an Int32 to a Float32 might lose precision
bar64(bar 1) # OK, a Float32 can be autocasted to a Float64
数値リテラルは、その型に関係なく、リテラルの実際の値がターゲット型に収まる場合は常にキャストされます。
(上記の最後の例のように)式は、コンパイラにno_number_autocast
フラグが渡されない限りキャストされます(コンパイラ機能を参照)。
曖昧さが存在する場合、例えば、複数の選択肢がある場合、コンパイラはエラーをスローします。
def foo(x : Int64)
x
end
def foo(x : Int128)
x
end
foo 1_i32 # Error: ambiguous call, implicit cast of Int32 matches all of Int64, Int128
現時点では、自動キャストは、これまで示した関数呼び出し時と、クラス/インスタンス変数の初期化時の2つのシナリオでのみ機能します。次の例は、インスタンス変数に対する2つの状況を示しています。初期化時のキャストは機能しますが、代入時のキャストは機能しません。
class Foo
@x : Int64 = 10 # OK, 10 fits in an Int64
def set_x(y)
@x = y
end
end
Foo.new.set_x 1 # Error: "at line 5: instance variable '@x' of Foo must be Int64, not Int32"
シンボルの自動キャスト¶
シンボルは列挙型メンバとして自動キャストされるため、より簡潔に記述できます。
enum TwoValues
A
B
end
def foo(v : TwoValues)
case v
in TwoValues::A
p "A"
in TwoValues::B
p "B"
end
end
foo :a # autocasted to TwoValues::A