Casts

Sometimes you have a value with a general type such as Object, but would like to convert the value to a more specific type (such as Str). You can do this by using casts.

Successful cast

Alore uses the as operator for casts:

var o as Object         -- Declare o to have type Object
o = 'foo'
o[0]                    -- Type check error: Object does not support [ ]
(o as Str)[0]           -- Ok after casting to Str (result 'f')

In the above example o has type Object, but we know that it really refers to a Str value. On the third line we cast the value to Str, allowing us to use all Str operations such as indexing.

Different uses of "as"

The as keyword is also used for declaring the types of variables. If ambiguous, the as is assumed to be a declaration, not a cast. Place a cast within parentheses if it may be confused with a declaration:

def F() as void
  var o = 'foo' as Object  -- Declaration, not a cast
  var s = (o as Str)       -- Cast; infer type Str for s
  var s = o as Str         -- Type check error: declaration with an incompatible initializer
                           -- (cannot assign Object to Str)
end

To more clearly see why the last variable definition is invalid, we rewrite it to use a separate assignment statement for initialization:

  ...
  var s as Str
  s = o                    -- Type check error: incompatible types
end

Failed casts

The as expression checks that the runtime value of the left operand has the expected type, and returns the left operand value unmodified. The type is specified by the right operand. If the operand does not have the expected value, it raises a CastError exception at runtime:

var o = 'foo' as Object
(o as Int) + 2           -- CastError: Cannot cast from Str to Int

The precedence of as

The as operator has a lower precedence than most other operators. Therefore the left operand rarely needs to be within parentheses:

var a = (obj.method(arg) + 5 as Int)  -- The entire expression obj... is the
                                      -- left operand of "as"

Invalid casts and converting values

Casts never modify the value of the left operand. For example, casting an Int value to Float results in a type check error, not a numeric conversion:

var i = 1 as Int
var f = (i as Float)     -- Type check error: Cast from Int to Float can never succeed

The cast can never succeed if the source and target types do not have a subtyping relationship, and the type checker reports this as an error.

The correct way to convert integers to floats is to call Float:

var i = 1 as Int
var f = Float(i)

Use Int to perform the inverse conversion:

var i = Int(2.2)

Casts to generic types and dynamic casts

Alore does not support casts to generic types such as Array<Int> or casts to tuple types (other than Tuple). However, the next section discusses dynamic casts which are often a good alternative to the unsupported cast operations.