私はNilで任意のメソッドを呼び出すことができ、これは間違っていると感じます


14

最近スクリプトのデバッグにかなりの時間を費やしましたが、ようやく問題が見つかったのは、次のようなコードが原因でした。

class Foo {
    has $.bar;
    method () {
        # do stuff
        $!.bar;
    }
}

これは、問題はそれにあったが、$!.barどちらかとなっているべき、$!barまたは$.bar。わかった

しかし、なぜこれが死なないのですか?

より詳細に本を見てみると、それはここでの問題のように見える私は(存在しない)メソッドを呼び出ししようとしているということであるbar$!、この時点である、Nil任意のエラーがされていないために。

そして、私は実際に私が望む任意のメソッドを呼び出すことができるように見えNil、それらはすべてNilNil.this-is-a-fake-methodやのようなものを含め、すべて黙って戻りNil.reverse-entropy(123)ます。

これは機能ですか?もしそうなら、理論的根拠は何ですか?

回答:


13

はい、意図され、文書化されています。の見出しNilは「値の不在または害のない障害」であり、クラスのドキュメントで言及されています

Nil存在しないメソッドのメソッド呼び出し、およびその結果としての添え字操作は成功し、を返しNilます。

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

概要2は、「Nil戻り値のすべての未定義メソッド呼び出しNil、つまり、Nilメソッド呼び出しチェーンを下に伝搬します。同様に、Nil戻り値の添え字演算Nil」のように、意図は、すべてのステップで$foo.Bar()[0].Baz()チェックを必要としないNil、または特別な「Nil-safe」のような式を許可しているようです"メソッド呼び出しと添え字演算子。


4
確かに。そして、かなり以前にも既に:github.com/rakudo/rakudo/commit/174727377f(2013年12月)関連する推測も参照:design.raku.org/S02.html#Nil
Elizabeth Mattijsen

1
@ElizabethMattijsenああ、私はS02が答えを持っていると思います。「returnでの未定義のメソッド呼び出しはすべて、メソッド呼び出しチェーンに伝達されNilます。」したがって、すべてのステップでnilテストや特別な種類の演算子を必要とせずに実行できることが意図されています(最後にnilを正しく処理する限り)。それを編集します、ありがとう。NilNil$foo.Bar().Baz().Blah()?.
ホッブズ

1
Nilエラーと戻ったばかりの、よりスローしないことは、NilOBJの-C、それは同じように使われているNSフレームワークではかなり広範囲に使用して取得します-無記号に渡しておくチェーンの通話が可能になります。例外の正確なパフォーマンス上のペナルティとそれらをキャッチすることはわかりませんが、Nil柔軟性が低い場合は、チェーンがより効率的になる可能性があると思います。
user0721090601

1
(しかし、それはまったく知られていない推測なので、lizmatまたはjnthnが私が間違っていることを教えてくれて、私は黙る必要があると言ってうれしい:
user0721090601

2
このNilクラスにはFALLBACK docs.raku.org/language/typesystem#index-entry-FALLBACK_(method) メソッドがあり、を返しますNil。基本的に、メソッドが見つからなかったために例外がスローされる直前に、チェックFALLBACKが行われ、可能であれば呼び出されます。
Elizabeth Mattijsen

5

この質問(とホッブズ答えは)また、私は感じて...不安作られた:私は最終的に見つけhttps://docs.raku.org/language/traps:それは割り当てがあることを説明しNil、通常は、異なる値を生成しますAny。次の基本的なREPL相互作用もこれを示しています。

> 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

((違い=とは:=:ここで覆われているhttps://docs.raku.org/language/containers#Binding))

...したがって、一般的な考えは、「存在しない値または良性の障害」は、通常のコードでは、私(そしておそらくあなたも同様)にはるかに広がっていないということです。直接、およびでメソッドを直接呼び出すことに関連する特定の偶発的な状況で一致します$!

これは、の違いについて、私はもっと認識さNilAny、そして提供根拠は私に多くの意味を成していました。


2
Nilコンテナをデフォルトの状態に設定します。デフォルト値を変更できます。my $foo is default(42) = 5; $foo = Nil; say $foo; # 42
Brad Gilbert
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.