List.indexOf
Scalaで、コレクション内の要素の位置を決定するためのさまざまなインデックスメソッド(たとえば、 )が、より慣用的なものではなく、コレクション内に特定の要素がないことを示すためにList.indexWhere
戻るのはなぜかといつも思っていました。の代わりに戻ることには特別な利点がありますか、それとも歴史的な理由だけですか?-1
Option[Int]
-1
None
3 に答える
それは単に歴史的な理由によるものですが、歴史的な理由が何であるかを知りたいのです。歴史は何であり、なぜそのようになったのでしょうか。
直前の履歴はjava.lang.String.indexOf
インデックスを返すメソッドであり、一致する文字が見つからない場合は -1 です。しかし、これは新しいことではありません。文字列に文字が見つからない場合、Fortran SCAN 関数は 0 を返します。これは、Fortran が 1-indexing を使用する場合と同じことです。
これを行う理由は、文字列には正の長さしかないためNone
、ボクシングのオーバーヘッドなしで負の長さを値として使用できるからです。 -1
は最も便利な負の数なので、それだけです。
そして、コンパイラがすべてのボックス化とボックス化解除、およびすべてが無関係であることを認識できるほど賢くない場合、これは合計される可能性があります。特に、オブジェクトの作成には 5 ~ 10 ns かかる傾向がありますが、関数の呼び出しまたは比較には通常 1 ~ 2 ns 程度かかるため、コレクションが短い場合、新しいオブジェクトの作成にはかなりの部分的なペナルティが発生する可能性があります (あなたのメモリにはすでに負荷がかかっており、GC にはやるべきことがたくさんあります)。
もし Scala が最初に素晴らしいオプティマイザを持っていたなら、選択はおそらく違っていたでしょう。なぜなら、より安全で特殊なケースではないオプションを使って書くだけで、コンパイラがそれを適切に高性能なものに変換することを信頼するからです。コード。
スピード?(わからない)
def a(): Option[Int] = Some(Math.random().toInt)
def b(): Int = Math.random().toInt
val t0 = System.nanoTime; (0 to 1000000).foreach(_ => a()); println("" + (System.nanoTime - t0))
// 53988000
val t0 = System.nanoTime; (0 to 1000000).foreach(_ => b()); println("" + (System.nanoTime - t0))
// 49273000
また、インデックス < 0 を常にチェックする必要がありますSome(index)
Int
を返すだけで Java の組み込み型を使用できるという利点もありますがOption[Int]
、整数を でラップする必要がありObject
ます。これは、(@idonnie で示されているように) 速度が低下するだけでなく、メモリ使用量も増加することを意味します。
は一般的なツールとして優れてOption
いますが (私はよく使用します)、その他の値のない表現 saDouble.NaN
または空の文字列も完全に有効であり、便利です。
使用する利点の 1 つは、コレクションとしてループなどOption
に渡す機能です。for
それを行う可能性が低い場合は、 -1 をチェックするか、 /NaN
の一致を行うよりも簡潔になる可能性があります。None
Some