Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
183 lines (123 sloc) 5.76 KB
=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 sub classes 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 a 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 { $_ }).perl.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, Perl 6 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␤»
=head1 Methods
=head2 method append
method append(*@)
Warns the user that they tried to append onto a C<Nil>.
=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>.
=head2 method push
method push(*@)
Warns the user that they tried to push onto a C<Nil>.
=head2 method unshift
method unshift(*@)
Warns the user that they tried to unshift onto a C<Nil>.
=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
You can’t perform that action at this time.