Rules / Types, classes & roles / basic

Nil Reference

Absence of a value

What it is #

Position in the hierarchy #

Inherits from
Does
Inherited byFailure

Routines #

Signatures are reproduced from the documentation, including their declared return types. A routine listed here is part of the type's published interface; whether Raku++ implements it is a separate question, answered by the examples below.

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 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) {}

Returns 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.

Examples, run three ways #

Every example below comes from the official documentation, together with the output that documentation asserts. Each was then executed by Rakudo and by Raku++ when this page was built. Where the three agree, one result is shown; where they do not, all three are — because which of them is wrong is exactly the information worth having.

1 all-differ · 4 no-output · 6 ok · 3 rakupp-differs

class Nil is Cool { }

Not executed: the documentation states no expected output for this example.

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

Documentation, Rakudo and Raku++ all agree.

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

Documentation, Rakudo and Raku++ all agree.

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␤»
Documentation
Nil
Nil
Nil
Nil
Nil
Rakudo
Nil
Nil
Nil
Nil
Nil
Raku++
(Any)
(Any)
(Any)
(Any)
(Any)

Raku++ disagrees with both the documentation and Rakudo — a defect.

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

Documentation, Rakudo and Raku++ all agree.

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

Documentation, Rakudo and Raku++ all agree.

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

Not executed: the documentation states no expected output for this example.

my Int $x = 42;
$x = Nil;
$x.say;                     # OUTPUT: «(Int)␤»
Output
(Int)

Documentation, Rakudo and Raku++ all agree.

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)»
Documentation
X::TypeCheck::Assignment: Type check failed in assignment to $y; expected Int but got Any (Any)
Rakudo
X::TypeCheck::Assignment: Type check failed in assignment to $i; expected Int:D but got Int (Int) (perhaps Nil was assigned to a :D which had no default?)
Raku++

All three differ. Needs a human.

Not yet examined. Which of these is correct has not been established — do not treat either engine as settled here.

sub g( --> Int:D ){ fail "oops" }; # this definedness constraint is ignored
my Any:D $h = g;                   # failure object matches Any:D, so is assigned

Not executed: the documentation states no expected output for this example.

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

Not executed: the documentation states no expected output for this example.

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)␤»
Output
(Any)
X::TypeCheck::Assignment: Type check failed in assignment to $y; expected Int but got Any (Any)

Documentation, Rakudo and Raku++ all agree.

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

Raku++ disagrees with both the documentation and Rakudo — a defect.

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␤»
Documentation
42
Rakudo
42
Raku++
-1

Raku++ disagrees with both the documentation and Rakudo — a defect.