T M
class Nil
Error ReportCollection examples

Absence of a value or a benign failure

class Nil is Cool { }

The value Nil may be used to fill a spot where a value would normally go, and in so doing, explicitly indicate that no value is present. It may also be used as a cheaper and less explosive alternative to a Failure. (In fact, class Failure is derived from Nil, so smartmatching Nil will also match Failure.)

The class Nil is the same exact thing as its only possible value, Nil.

say Nil === Nil.new;        # OUTPUT: «True␤»

Along with Failure, Nil and its subclasses may always be returned from a routine even when the routine specifies a particular return type. It may also be returned regardless of the definedness of the return type, however, Nil is considered undefined for all other purposes.

sub a--> Int:D ) { return Nil }
a().say;                    # OUTPUT: «Nil␤»

Nil is what is returned from empty routines or closure, or routines that use a bare return statement.

sub a { }a().say;         # OUTPUT: «Nil␤» 
sub b { return }b().say;  # OUTPUT: «Nil␤» 
say (if 1 { });             # OUTPUT: «Nil␤» 
{ ; }().say;                # OUTPUT: «Nil␤» 
say EVAL "";                # OUTPUT: «Nil␤»

In a list, Nil takes the space of one value. Iterating Nil behaves like iteration of any non-iterable value, producing a sequence of one Nil. (When you need the other meaning, the special value Empty is available to take no spaces when inserted into list, and to return no values when iterated.)

(1Nil3).elems.say;      # OUTPUT: «3␤» 
(for Nil { $_ }).raku.say;  # OUTPUT: «(Nil,)␤»

Any method call on Nil of a method that does not exist, and consequently, any subscripting operation, will succeed and return Nil.

say Nil.ITotallyJustMadeThisUp;  # OUTPUT: «Nil␤» 
say (Nil)[100];                  # OUTPUT: «Nil␤» 
say (Nil){100};                  # OUTPUT: «Nil␤»

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, Raku assumes Any.

Since a hash assignment expects two elements, use Empty not Nil, e.g.

my %h = 'a'..'b' Z=> 1..*;
# stuff happens 
%h = Empty# %h = Nil will generate an error

However, if the container type is constrained with :D, assigning Nil to it will immediately throw an exception. (In contrast, an instantiated Failure matches :D because it's a definite value, but will fail to match the actual nominal type unless it happens to be a parent class of Failure.) Native types can not have default values nor hold a type object. Assigning Nil to a native type container will fail with a runtime error.

my Int $x = 42;
$x = Nil;
$x.say;                     # OUTPUT: «(Int)␤» 
 
sub f--> Int:D ){ Nil };  # this definedness constraint is ignored 
my Int:D $i = f;            # this definedness constraint is not ignored, so throws 
CATCH { default { put .^name''.Str } };
# OUTPUT: «X::TypeCheck::Assignment: Type check failed in assignment to $y; expected Int but got Any (Any)» 
 
sub g--> Int:D ){ fail "oops" }# this definedness constraint is ignored 
my Any:D $h = g;                   # failure object matches Any:D, so is assigned

but

my Int:D $j = g;
# It will throw both exceptions: 
# Earlier failure: 
#  oops 
#   in sub g at <unknown file> line 1 
#   in block <unit> at <unknown file> line 1 
# 
# Final error: 
#  Type check failed in assignment to $j; expected Int:D but got Failure (Failure.new(exception...) 
#   in block <unit> at <unknown file> line 1 

Because an untyped variable is type Any, assigning a Nil to one will result in an (Any) type object.

my $x = Nil;
$x.say;          # OUTPUT: «(Any)␤» 
my Int $y = $x;  # will throw an exception 
CATCH { default { put .^name''.Str } };
# OUTPUT: «X::TypeCheck::Assignment: Type check failed in assignment to $y; expected Int but got Any (Any)␤»

If you are looking for a variable which transforms objects into type objects when said variable appears on the right-hand side, you can type the container as Nil.

my Nil $x;
my Str $s = $x;
$s.say;          # OUTPUT: «(Str)␤»

There is an important exception to this transforms-into-type-object rule: assigning Nil to a variable which has a default will restore that default.

my Int $x is default(42= -1;
my $y = 1;
for $x$y -> $val is rw { $val = Nil unless $val > 0 }
$x.say;          # OUTPUT: «42␤»

Methods such as BIND-POS, ASSIGN-KEY, ASSIGN-POS will die; BIND-KEY will produce a failure with an X::Bind exception in it, and STORE will produce an X::Assignment::RO exception.

Methods

method append

method append(*@)

Warns the user that they tried to append onto a Nil (or derived type object).

method gist

method gist(--> Str:D)

Returns "Nil".

method Str

method Str()

Warns the user that they tried to stringify a Nil.

method new

method new(*@)

Returns Nil

method prepend

method prepend(*@)

Warns the user that they tried to prepend onto a Nil or derived type object.

method push

method push(*@)

Warns the user that they tried to push onto a Nil or derived type object.

method unshift

method unshift(*@)

Warns the user that they tried to unshift onto a Nil or derived type object.

method ords

Returns an empty Seq, but will also issue a warning depending on the context it's used (for instance, a warning about using it in string context if used with say).

method chrs

Will return \0, and also throw a warning.

method FALLBACK

method FALLBACK(| --> Nil{}

The fallback method takes any arguments and always returns a Nil.

method Numeric

method Numeric()

Warns the user that they tried to numify a Nil.