Absence of a value or a benign failure
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 )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 ; 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); # 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 = 'a'..'b' Z=> 1..*;# stuff happens= 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 = 42;= Nil;.say; # OUTPUT: «(Int)»sub f( --> Int ); # this definedness constraint is ignoredmy Int = f; # this definedness constraint is not ignored, so throwsCATCH ;# OUTPUT: «X::TypeCheck::Assignment: Type check failed in assignment to $y; expected Int but got Any (Any)»sub g( --> Int ); # this definedness constraint is ignoredmy Any = g; # failure object matches Any:D, so is assigned
but
my Int = 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 = Nil;.say; # OUTPUT: «(Any)»my Int = ; # will throw an exceptionCATCH ;# 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 ;my Str = ;.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 is default(42) = -1;my = 1;for , -> is rw.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.
method append(*@)
Warns the user that they tried to append onto a Nil
(or derived type object).
method gist(--> Str)
Returns "Nil"
.
method Str()
Warns the user that they tried to stringify a Nil
.
method new(*@)
Returns Nil
method prepend(*@)
Warns the user that they tried to prepend onto a Nil
or derived type object.
method push(*@)
Warns the user that they tried to push onto a Nil
or derived type object.
method unshift(*@)
Warns the user that they tried to unshift onto a Nil
or derived type object.
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
).
Will return \0
, and also throw a warning.
method FALLBACK(| --> Nil)
The fallback method takes any arguments and always returns a Nil.
method Numeric()
Warns the user that they tried to numify a Nil
.