Type grammar
When:
- specifying type restrictions
- specifying type arguments
- declaring variables
- declaring aliases
- declaring typedefs
- the argument of an is_a? pseudo-call
- the argument of an as expression
- the argument of a sizeof expression
- the argument of an instance_sizeof expression
- a method's return type
a convenient syntax is provided for some common types. These are especially useful when writing C bindings, but can be used in any of the above locations.
Paths and generics
Regular types and generics can be used:
Int32
My::Nested::Type
Array(String)
Union
alias Int32OrString = Int32 | String
The pipe (|
) in types creates a union type. Int32 | String
is read "Int32 or String". In regular code, Int32 | String
means invoking the method |
on Int32
with String
as an argument.
Nilable
alias Int32OrNil = Int32?
is the same as:
alias Int32OrNil = Int32 | ::Nil
In regular code, Int32?
is an Int32 | ::Nil
union type itself.
Pointer
alias Int32Ptr = Int32*
is the same as:
alias Int32Ptr = Pointer(Int32)
In regular code, Int32*
means invoking the *
method on Int32
.
StaticArray
alias Int32_8 = Int32[8]
is the same as:
alias Int32_8 = StaticArray(Int32, 8)
In regular code, Int32[8]
means invoking the []
method on Int32
with 8
as an argument.
Tuple
alias Int32StringTuple = {Int32, String}
is the same as:
alias Int32StringTuple = Tuple(Int32, String)
In regular code, {Int32, String}
is a tuple instance containing Int32
and String
as its elements. This is different than the above tuple type.
NamedTuple
alias Int32StringNamedTuple = {x: Int32, y: String}
is the same as:
alias Int32StringNamedTuple = NamedTuple(x: Int32, y: String)
In regular code, {x: Int32, y: String}
is a named tuple instance containing Int32
and String
for x
and y
. This is different than the above named tuple type.
Proc
alias Int32ToString = Int32 -> String
is the same as:
alias Int32ToString = Proc(Int32, String)
To specify a Proc without parameters:
alias ProcThatReturnsInt32 = -> Int32
To specify multiple parameters:
alias Int32AndCharToString = Int32, Char -> String
For nested procs (and any type, in general), you can use parentheses:
alias ComplexProc = (Int32 -> Int32) -> String
In regular code Int32 -> String
is a syntax error.
self
self
can be used in the type grammar to denote a self
type. Refer to the type restrictions section.
class
class
is used to refer to a class type, instead of an instance type.
For example:
def foo(x : Int32)
"instance"
end
def foo(x : Int32.class)
"class"
end
foo 1 # "instance"
foo Int32 # "class"
class
is also useful for creating arrays and collections of class type:
class Parent
end
class Child1 < Parent
end
class Child2 < Parent
end
ary = [] of Parent.class
ary << Child1
ary << Child2
Underscore
An underscore is allowed in type restrictions. It matches anything:
# Same as not specifying a restriction, not very useful
def foo(x : _)
end
# A bit more useful: any two-parameter Proc that returns an Int32:
def foo(x : _, _ -> Int32)
end
In regular code _
means the underscore variable.
typeof
typeof
is allowed in the type grammar. It returns a union type of the type of the passed expressions:
typeof(1 + 2) # => Int32
typeof(1, "a") # => (Int32 | String)
To the extent possible under law, the persons who contributed to this workhave waived
all copyright and related or neighboring rights to this workby associating CC0 with it.
https://crystal-lang.org/reference/syntax_and_semantics/type_grammar.html