Perl5 -> Perl 6: everything is an object!

What does it mean everything is an object? Coming from other OOP languages this statement could be clear, but not all the languages adhere to it strictly. In Perl 6 everything is an object means that even not assigned values are objects!

Nil is always the same

First of all, Perl 6 declares the special class [Nil]( that is a placeholder for null values. With two particular exceptions:
  1. a Nil value is an object (so you can call methods on it);
  2. a Nil object is always equal to another Nil object (i.e., there is only one version of being null!).
A not initialized value does not get a Nil value for free, the type Nil can be explicity used by a developer to indicate the variable still does not contain any particular value.

Any is all

The special type [Any]( is the de-facto base class for everything in Perl 6. Well, the special class [Mu]( is the root of the class hierarchy in Perl 6, but as the documentation states:
Note that most classes do not derive from Mu directly, but rather from Any.
that means that Any is the thing used as concrete root for the classes in Perl 6. Any unassigned value in Perl 6 got assigned to Any.


Perl 6 provides special methods to introspect a variable, that is a class instance, that is in turn an object. Let’s start simple:
"\nDumping a string scalar".say;
my $var = 'Hello World';
say 'NAME -> ' ~ $var.^name;
say 'PERL -> ' ~ $var.perl;
say 'WHO -> '  ~ $var.WHO;
say 'VAR -> '  ~ $var.VAR;
say 'WHICH -> '~ $var.WHICH;

"\nDumping a list".say;
my @list = ( 1, 2, 3, 4);
say 'NAME -> ' ~ @list.^name;
say 'PERL -> ' ~ @list.perl;
say 'WHO -> '  ~ @list.WHO;
say 'VAR -> '  ~ @list.VAR;
say 'WHICH -> '~ @list.WHICH;
will produce the output:
Dumping a string scalar
NAME -> Str
PERL -> "Hello World"
WHO -> Str
VAR -> Hello World
WHICH -> Str|Hello World

Dumping a list
NAME -> Array
PERL -> [1, 2, 3, 4]
WHO -> Array
VAR -> 1 2 3 4
WHICH -> Array|94409967984048
As you can see, the scalar variable is of type Str and the array is not surprisingly of type Array. The perl method provides a common way to get a Perl 6 representation of the instance value, so for example the string or the list. What about an empty value? As already stated, a not initialized value got Any:
"\nDumping an empty value".say;
my @elist;
say 'NAME -> ' ~ @elist.^name;
say 'PERL -> ' ~ @elist.perl;
say 'WHO -> '  ~ @elist.WHO;
say 'VAR -> '  ~ @elist.VAR;
say 'WHICH -> '~ @elist.WHICH;
say 'DEFINED -> ' ~ @elist.defined;

"\nDumping an empty scalar".say;
my $empty;
say 'NAME -> '    ~ $empty.^name;
say 'PERL -> '    ~ $empty.perl;
say 'WHO -> '     ~ $empty.WHO;
say 'WHICH -> '   ~ $empty.WHICH;
say 'DEFINED -> ' ~ $empty.defined;
that produces the following output:
Dumping an empty value
NAME -> Array
PERL -> []
WHO -> Array
VAR ->
WHICH -> Array|94409968050448

Dumping an empty scalar
NAME -> Any
PERL -> Any
WHO -> Any
WHICH -> Any|U94409927114704
DEFINED -> False
Here you can see how Perl 6 is smarter than the developer: an empty array got an attached instance of type Array, as expected, and also such instance is defined: the fact that the array is empty is a property of the array, not of the variable itself. The same is not true for an empty scalar, that in this case got a Any value and is also not defined. Assigning explicitly a Nil value to a scalar produces the very same output:
"\nDumping a Nil value".say;
$empty = Nil;
say 'NAME -> '    ~ $empty.^name;
say 'PERL -> '    ~ $empty.perl;
say 'WHO -> '     ~ $empty.WHO;
say 'WHICH -> '   ~ $empty.WHICH;
say 'DEFINED -> ' ~ $empty.defined;
and you can see the output as
Dumping a Nil value
NAME -> Any
PERL -> Any
WHO -> Any
WHICH -> Any|U94299069706192
DEFINED -> False

Where is my Nil?

Assigning Nil to a variable and getting it is of type Any can be confusing at glance, but the documentation states it clearly:
When assigned to a container, the Nil value (but not any subclass of Nil) will attempt to revert the container to its default value; if no such default is declared, Perl 6 assumes Any.
In other words, each time you assign Nil to a variable (container) it tries to force the undefined value on the container placing its type to the default one (the one used in the declaration) or Any. This can be better understood with the following example:
my Str $string = Nil;
"\nDumping a Nil Str".say;
say 'NAME -> '    ~ $string.^name;
say 'PERL -> '    ~ $string.perl;
say 'WHO -> '     ~ $string.WHO;
say 'WHICH -> '   ~ $string.WHICH;
say 'DEFINED -> ' ~ $string.defined;
that this time produces a not defined Str value:
Dumping a Nil Str
NAME -> Str
PERL -> Str
WHO -> Str
WHICH -> Str|U94701194870208
DEFINED -> False

Containers: the magic behind the everything is an object

The above discussion cannot be complete without speaking about containers, that are that level of abstraction that makes the everything is an object statement possible in Perl 6. The idea is simple: in Perl 6 the term variable means a name to a container, being the container a reference to the actual value. That means that a variable is not a user-level object, rather an indirection layer between the user and the value stored in the container. Each time Perl 6 encounters a new variable, it stores it in a lexical pad (a table of variables, for short) with a ponter to the container instance of such type. This means, for instance, that when a my Str $string variable is declared, Perl 6 stores an entry in the variable table with the name $string and a pointer to an instance of the container, in this case a Str object. This essentially intiializes the variable to the container itself, allowing for introspection and elaboration on the object itself even if the variable has not been assigned to a value. Once the variable got assigned, the container takes an action to track the content. In the case of a Scalar container, it simply substitutes itself with the content instance, in the case of a complex container (e.g., an Array) it can be append the content to the previous one. The [Scalar]( container can be seen via the special VAR method:
my Str $empty_string;
my @empty_array;

say 'NAME -> '      ~ $empty_string.^name;
say 'DEFINED -> '   ~ $empty_string.defined;
say 'CONTAINER -> ' ~ $empty_string.VAR.^name;
say "\n";

say 'NAME -> '      ~ @empty_array.^name;
say 'DEFINED -> '   ~ @empty_array.defined;
say 'CONTAINER -> ' ~ @empty_array.VAR.^name;
say "\n";
and it produces an output similar to the following:
NAME -> Str
DEFINED -> False

NAME -> Array
of course, in the case of an array the container is not a Scalar.

The Scalar container enters whenever a $ sigil is used

It is a quite simple rule of thumb: if it seems a scalar, its container is a Scalar. So for instance, the following piece of code:
for ( $empty_string, @empty_array ) -> $_ {
    say 'NAME -> '      ~ $_.^name;
    say 'DEFINED -> '   ~ $_.defined;
    say 'CONTAINER -> ' ~ $_.VAR.^name;
    say "\n";
does not produce the same output as the former example, as well as does not produce an Array container for the array:
NAME -> Str
DEFINED -> False

NAME -> Array
The fact is that every time you assign something to a $-variable it will go thru a Scalar container, no matter what the actual value is. This does not mean the content will be lost, and in fact a good thing about Scalar containes is that it does delegate pretty much every method call to the content itself.


In Perl 6 each variable holds a container, the container knows how to manipulate the data inside it. The Scalar container is used pretty much everywhere a $ sigil appears, and it does delegate method calls to its real content (e.g., a Str). When Perl 6 encounters a variable, it does place a container instance into it, allowing for a variable to never be null, and relying on the defined-ness of the container content for knowing if it has a value or not. The special value Nil is used as a placeholder for none-value at all, but when it used against a container (i.e., assigned to a variable) it does reset the container to its default value, never appearing therefore within a single variable.

The article Perl5 -> Perl 6: everything is an object! has been posted by Luca Ferrari on December 14, 2017