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.)
(1, Nil, 3).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
.