Perl 6 native types

Using the types the compiler and hardware make available to you

Perl 6 offers a set of native types with a fixed, and known, representation in memory. This page shows which ones exist and how they can be used. Please check also the page on native numerics for more information on them.

Types with native representation

Some simple types in Perl 6 have a native representation, indicating that they will use the C language representation provided by the compiler, operating system and machine. These are the four native types available:

int Equivalent to Int (with limited range)
uint Equivalent to Int (with limited range) with the unsigned trait
num Equivalent to Num
str Equivalent to Str

However, these types do not necessarily have the size that is required by the NativeCall interface (e.g., Perl 6's int can be 8 bytes but C's int is only 4 bytes); the types below will have to be used instead of the types int or num listed above.

In general, these variables will behave in the same way as regular scalar variables, in a behavior that is called auto-boxing; however, there are some differences, since what you are actually declaring is how they will be represented, not their actual type. The first one is that their type will be actually their equivalent type, not their native type.

my int $intillo = 3;
say $intillo.^name# OUTPUT: «Int␤» 

This obviously means that they will smartmatch their equivalent (auto-boxed) type, not their native type:

my str $strillo = "tres";
say $strillo ~~ str# OUTPUT: «False␤» 
say $strillo ~~ Str# OUTPUT: «True␤» 

This is due to the fact that Natives don't know their types because they're just values, without any meta-data. In multi-dispatch, you can have a native candidate, but you cannot differentiate different sizes of the same native type. That is, you can have an Int and int candidates, but there would be an ambiguity between int, atomicint, int64, etc. candidates.

They cannot be bound either. Trying to do my num $numillo := 3.5 will raise the exception Cannot bind to natively typed variable '$variable-name'; use assignment instead.

int @ num @ str @ Native types can also be composite.

m: my int @intillos = ^10_000_000;
say [+@intillos# OUTPUT: «49999995000000␤» 

native array In this case, native-ness extends to the composite type, which will be array

my num @many-pi  = ^8 »*» π ; say @many-pi.^name ;# OUTPUT: «array[num]␤» 

Native arrays are Iterable, but they are not a subclass of List. However, they behave similarly to Arrays; for instance, they can be shaped:

my str @letter-pairs[10= 'a'..'j' Z~ 'A'..'J';
say @letter-pairs.perl;
# OUTPUT: «array[str].new(:shape(10,), ["aA", "bB", "cC", "dD", "eE", "fF", "gG", "hH", "iI", "jJ"])␤» 

Types with native representation and size

What has been mentioned about types with native representation also applies here; they will be auto-boxed to Perl 6 types and will not be boundable. However, these types, which are listed in the table below, have the characteristic of being usable in NativeCall functions.

int8 (int8_t in C, also used for char)
int16 (int16_t in C, also used for short)
int32 (int32_t in C, also used for int)
int64 (int64_t in C)
byte, uint8 (uint8_t in C, also used for unsigned char)
uint16 (uint16_t in C, also used for unsigned short)
uint32 (uint32_t in C, also used for unsigned int)
uint64 (uint64_t in C)
num32 (float in C)
num64 (double in C)

These types have a fixed size representation which is independent of the platform, and thus can be used safely for those native calls. Nothing prevents us from using them in any other environment, if we so wish. In the same way as the types above, this size will have to be taken into account when assigning values to variables of this type:

my byte $intillo = 257;
say $intillo# OUTPUT: «1␤» 

Since byte is able to hold only 8 bits, it will wrap over and assign the result of the original value modulo 256, which is what is shown.

The main difference between types with declared native size and those without is the use of is nativesize in their declaration. For instance, int8 is declared in this way:

my native int8 is repr('P6int'is Int is nativesize8{ }

Indicating that it will use, besides an integer representation (P6int), a native size of only 8 bits. This trait, however, is not intended to be used in your programs since it is not part of the Perl 6 specification.

The void type

The native void type corresponds to the C void type. Although, being a valid type, you can use it in expressions:

use NativeCall;
my void $nothing;
say $nothing.perl# OUTPUT: «NativeCall::Types::void␤» 

In practice, it is an Uninstantiable type that can rarely be used by itself, and in fact it is explicitly forbidden in return types. However, it is generally found in typed pointers representing the equivalent to the void * pointer in C.

sub mallocint32 $size --> Pointer[void] ) is native { * };
my Pointer[void$for-malloc = malloc32 );
say $for-malloc.perl;

You can also nativecast Blobs to this kind of pointer in case you need to work with them in native functions that use the type

use NativeCall;
my Pointer[void$native = nativecast(Pointer[void], Blob.new(0x220x33));

However, outside that, the functionality it offers is quite limited, since pointers to void cannot be dereferenced:

use NativeCall;
my Pointer[void$native = nativecast(Pointer[void], Buf.new(0x220x33));
say $native.deref# ERROR OUTPUT: «Internal error: unhandled target type␤» 

Atomic types

In this context, atomic refers to safe operation under threading. Perl 6 provides a type, atomicint, and some operations which, together, guarantee this. Please check the atomic operations section on the Numerics page for more information on this.

Rakudo specific native types

The types described in this section are Rakudo specific, so they are not guaranteed to be in other implementations or remain the same in future versions.

long (long in C)
longlong (longlong in C)
ulong (long and unsigned in C)
ulonglong (longlong and unsigned in C)
size_t (size_t and unsigned in C)
ssize_t (size_t in C)
bool (bool in C)

You can use them in the same way they would be used in native C:

use NativeCall;
 
my $just-an-array = CArray[int32].new12345 );
 
loop ( my size_t $i = 0$i < $just-an-array.elems$i++ ) {
    say $just-an-array[$i];
}

Which would print the five elements of the array, as it should be expected.