# Basic Types

Haxe provides several basic types :

• `Int` and `Float` for numeric values (read below)
• `Bool` for booleans (can be either `true` or `false`)

# Numeric Types

Haxe provides two basic numeric types : `Int` for integer values and `Float` for floating-point values.

Numerical operations `+, -, *, /` between these two numeric types are conservative (adding two `Int` together gives an `Int`) expect for the divide operator which always return a `Float`.

Bitwise operations `<<, >>, >>>, &, |, ^, ~` only operates on two `Int` and return an `Int`.

## Conversion

Every `Int` value can be used at the place a `Float` value is otherwise required.

OTOH in order to convert an `Float`' to an `Int` you need to use one of the following methods :

• `Std.int` : will round towards zero, usually the fastest operation
• `Math.round` : will round to the nearest
• `Math.ceil` : will round towards positive infinity
• `Math.floor` : will round towards negative infinity

## Overflows

In order to preserve the best available performance, Haxe does not enforce any kind of overflow behavior, it is then platform-dependent.

Here's some notes about the way overflows are performed per-platform :

• CPP, Java and C# are using real 32-bits int values, with the corresponding overflow
• Flash AVM2 is also using real 32-bits values but higher integers are memory-boxed so slower
• PHP, JS and Flash8 does not have native Int values, so the overflow will only occur if the value reach the float limit (2^52 for double). However all bitwise operations will result in a 32-bits overflow
• Neko has 31-bits int values in order to differentiate between unboxed integers and boxed pointers. Please note that you still have 1 bit of sign and 30 bits of data, so the maximum positive integer is 2^30-1 = 0x3FFFFFFF and the maximum negative integer is -2^30 = 0xC0000000

You can use the haxe.Int32 and haxe.Int64 api to perform operations which correctly overflow on both 32 and 64 bits, whatever the platform it's running on.

# Nullability

In order to keep native behavior and avoid performances problems, Haxe specification allow two behaviors for basic types concerning their ability to be ''null'.

The reason behind this differences is that Haxe want to get the best speed for each platform, and then needs to make a few compromises :

• making all type nullables would slowdown static platforms a lot
• making sure all `null` values are transformed into the corresponding default value would slowdown dynamic platforms a lot

So instead of enforcing a single behavior, we prefer to specify how Haxe will behave, so developers can plan or adapt their code accordingly. The compiler error messages will also greatly help in the transition between different types of platforms.

## Dynamic Platforms

On dynamic platforms (JS,PHP,Neko,Flash8) : every value can be `null`, and is `null` by default if not initialized, you can freely test for `null` equality without having to provide extra type information.

## Static Platforms

On static platforms (Flash, CPP, Java, C#), basic types have their own default values :

• every `Int` is by default initialized to 0
• every `Float` is by default initialized to `NaN` on Flash9+, and to 0.0 on CPP, Java and C#
• every `Bool` is by default initialized to `false`

It is not possible to store a `null` value into a basic type, unless you type it using `Null<T>` modifier :

```var a : Int = null; // error on static platforms
var b : Null<Int> = null; // allowed```

It is also not possible to compare a basic type value, unless you type it using `Null<T>` modifier :

```var a : Int = 0;
if( a == null ) { ... } // error on static platforms
var b : Null<Int> = 0;
if( b != null ) { .... } // allowed```

If you assign a `Null<T>` (or a `Dynamic`) value which contains `null` to the corresponding (unnullable) basic type, you will get the default value instead :

```var n : Null<Int> = null;
var a : Int = n;
trace(a); // 0 on static platforms```

## Optional Parameters and Nullability

Optional parameters have also a specific behavior with regards to nullability.

In particular, we have to be able to make the difference between native optional parameters which are not nullable and Haxe ones which might be nullable. This diffence is made by the usage of a question-mark optional parameter :

```// x is Int (not nullable)
function foo( x : Int = 0 ) {...}
// y is Null<Int> (nullable)
function bar( ?y : Int ) {...}
// z is also Null<Int>
function opt( ?z : Int = -1 ) {...}```

In the case the optional parameter is nullable, then we can pass it `null` and check for `null` in all cases. If we omit the parameter when calling the method, the default value will be use (if any exist) or `null` instead.

In the case the optional parameter is not nullable, then we cannot pass `null` or check for `null` on static platforms. If we omit the parameter when calling the method, the default value will be used anyway.

## Impact on Standard Library

The standard library correctly type the cases when a nullable value can be returned, for instance Hash.get will return `Null<T>` and you can safely check for `null` after reading from a hash table :

```var h = new Hash<Int>();
var x = h.get("hello");
trace(x); // null on all platforms```

However please note that `Hash.set` will only be able to set the exact type specified in the hash table :

```var h = new Hash<Int>();
h.set("hello",null); // error on static platforms
var h2 = new Hash<Null<Int>>();
h.set("hello",null); // allowed```

Array is another case that you need to be careful with : every access outside its allocated range will return the default value for the basic type, unless of course the content of the `Array` is nullable :

```var a = new Array<Int>();
trace(a[5]); // 0 on static platforms
a.push(null); // not allowed on static platforms
var b = new Array<Null<Int>>();
trace(b[5]); // null
b.push(null); // allowed```

## Impact on cross-platformability

There are two cases to consider when porting some code here.

Porting some code from a dynamic platform to a static one (from JS to CPP for instance) is quite easy : every place you compare with a `null` you will get an error message and all you will have to do is to set the corresponding basic type to be `Null` :

```var x : Int = 0;
...
if( flag ) x = null; // error```

Can be changed to :

```var x : Null<Int> = 0;
...```

Porting some code from a static platform to a dynamic one require a bit more work : it will require you to ensure that all object member variables are correctly initialized to their default value in the class constructor :

```class Point {
var x : Int;
var y : Int;
public function new() {
// ensure correct initialization on dynamic platforms
x = y = 0;
}
}```

You will also have to make sure that you don't check for `== 0` when for instance reading outside of an `Array`. In that case you can either make the Array contain nullable value, or if you want to get best performances and can be sure that your code logic will not store any `0` value in the array use conditional compilation to perform the check depending on the platform :

```static inline var OUTSIDE : Int = #if js null #else 0 #end;

var a = new Array<Int>();
var out : Int = a[5];
if( out == OUTSIDE ) {
....
}```

## Impact on Speed

Please be aware than using `Null` modifier will make the manipulation of this value slower because it will usually require allocating some memory block to be able to differentiate between a null and an actual real value. However this will usually be more optimized than trying to emulate the same behavior by yourself.

version #15307, modified 2012-08-09 16:59:58 by jan_flanders