Type grammar

When:

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:

  1. Int32
  2. My::Nested::Type
  3. Array(String)

Union

  1. 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

  1. alias Int32OrNil = Int32?

is the same as:

  1. alias Int32OrNil = Int32 | ::Nil

In regular code, Int32? is a syntax error.

Pointer

  1. alias Int32Ptr = Int32*

is the same as:

  1. alias Int32Ptr = Pointer(Int32)

In regular code, Int32* means invoking the * method on Int32.

StaticArray

  1. alias Int32_8 = Int32[8]

is the same as:

  1. alias Int32_8 = StaticArray(Int32, 8)

In regular code, Int32[8] means invoking the [] method on Int32 with 8 as an argument.

Tuple

  1. alias Int32StringTuple = {Int32, String}

is the same as:

  1. 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

  1. alias Int32StringNamedTuple = {x: Int32, y: String}

is the same as:

  1. 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

  1. alias Int32ToString = Int32 -> String

is the same as:

  1. alias Int32ToString = Proc(Int32, String)

To specify a Proc without arguments:

  1. alias ProcThatReturnsInt32 = -> Int32

To specify multiple arguments:

  1. alias Int32AndCharToString = Int32, Char -> String

For nested procs (and any type, in general), you can use parentheses:

  1. 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:

  1. def foo(x : Int32)
  2. "instance"
  3. end
  4. def foo(x : Int32.class)
  5. "class"
  6. end
  7. foo 1 # "instance"
  8. foo Int32 # "class"

class is also useful for creating arrays and collections of class type:

  1. class Parent
  2. end
  3. class Child1 < Parent
  4. end
  5. class Child2 < Parent
  6. end
  7. ary = [] of Parent.class
  8. ary << Child1
  9. ary << Child2

Underscore

An underscore is allowed in type restrictions. It matches anything:

  1. # Same as not specifying a restriction, not very useful
  2. def foo(x : _)
  3. end
  4. # A bit more useful: any two arguments Proc that returns an Int32:
  5. def foo(x : _, _ -> Int32)
  6. end

typeof

typeof is allowed in the type grammar. It returns a union type of the type of the passed expressions:

  1. typeof(1 + 2) # => Int32
  2. typeof(1, "a") # => (Int32 | String)