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 return Nil.

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.

Tags:

Raku