I can call any method on Nil and this feels wrong
It's intended and documented, yes. The headline for Nil
is "Absence of a value or a benign failure", and the class documentation mentions
Any method call on
Nil
of a method that does not exist, and consequently, any subscripting operation, will succeed and returnNil
.say Nil.ITotallyJustMadeThisUp; # OUTPUT: «Nil» say (Nil)[100]; # OUTPUT: «Nil» say (Nil){100}; # OUTPUT: «Nil»
Synopsis 2 states "Any undefined method call on Nil
returns Nil
, so that Nil
propagates down method call chains. Likewise any subscripting operation on Nil
returns Nil
", so the intent seems to be allowing expressions like $foo.Bar()[0].Baz()
without requiring checks for Nil
at every step, or special "Nil-safe" method call and subscripting operators.
This question (and hobbs' answer) also made me feel... uneasy: I eventually found https://docs.raku.org/language/traps: it explains that assigning Nil
produces a different value, usually Any
. The following basic REPL interaction also demonstrates this:
> my $foo = Nil
(Any)
> $foo.bar
No such method 'bar' for invocant of type 'Any'
in block <unit> at <unknown file> line 1
> my $bar := Nil
Nil
> $bar.baz
Nil
(( the difference between =
and :=
is covered here: https://docs.raku.org/language/containers#Binding ))
...so the general idea is that the 'absent value or benign failure' is far less widespread in regular code than I (and perhaps you as well?) suddenly feared: it does occur however, when you are going to work with regex matches directly and in your particular accidental situation related to directly invoking methods on $!
.
This made me more aware about the difference between Nil
and Any
, and the provided rationale made more sense to me.