=begin pod :kind("Type") :subkind("class") :category("basic")

=TITLE class Nil

=SUBTITLE Absence of a value or a benign failure

    class Nil is Cool { }

The value C<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
L<C<Failure>|/type/Failure>.  (In fact, class C<Failure> is derived from C<Nil>,
so smartmatching C<Nil> will also match C<Failure>.)

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

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

Along with C<Failure>, C<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, C<Nil>
is considered undefined for all other purposes.

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

C<Nil> is what is returned from empty routines or closure, or routines
that use a bare C<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, C<Nil> takes the space of one value.  Iterating C<Nil>
behaves like iteration of any non-iterable value, producing a sequence
of one C<Nil>. (When you need the other meaning, the special value
L<Empty|/type/Slip#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 C<Nil> of a method that does not exist,
and consequently, any subscripting operation, will succeed and return
C<Nil>.

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

X<|Nil assignment>
When assigned to a L<container|/language/containers>, the C<Nil> value (but not any subclass of
C<Nil>) will attempt to revert the container to its default value; if no
such default is declared, Raku assumes C<Any>.

Since a hash assignment expects two elements, use C<Empty> not C<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 C<:D>, assigning C<Nil> to it will immediately throw
an exception.  (In contrast, an instantiated C<Failure> matches C<: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 C<Failure>.) Native types can
not have default values nor hold a type object. Assigning C<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

=for code :skip-test<compile time error>
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 C<Any>, assigning a C<Nil> to one
will result in an L<(Any)|/type/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 C<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 C<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 C<BIND-POS>, C<ASSIGN-KEY>, C<ASSIGN-POS> will die;
C<BIND-KEY> will produce a failure with an C<X::Bind> exception in it, and
C<STORE> will produce an L<C<X::Assignment::RO>|https://docs.raku.org/type/X::Assignment::RO> exception.

=head1 Methods

=head2 method append

    method append(*@)

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

=head2 method gist

    method gist(--> Str:D)

Returns C<"Nil">.

=head2 method Str

    method Str()

Warns the user that they tried to stringify a C<Nil>.

=head2 method new

    method new(*@)

Returns C<Nil>

=head2 method prepend

    method prepend(*@)

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

=head2 method push

    method push(*@)

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

=head2 method unshift

    method unshift(*@)

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

=head2 method ords

Returns an empty C<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 C<say>).

=head2 method chrs

Will return C<\0>, and also throw a warning.

=head2 method FALLBACK

    method FALLBACK(| --> Nil) {}

The L<fallback method|/language/typesystem#index-entry-FALLBACK_(method)>
takes any arguments and always returns a L<Nil|/type/Nil>.

=head2 method Numeric

    method Numeric()

Warns the user that they tried to numify a C<Nil>.

=end pod

# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6
