は非常に一般的なEnumerator
インターフェイスであり、通過する「コレクション」について非常に単純な仮定のみを行います。特に、実際には 2 つの操作しかサポートしていません。現在の要素を取得し、次の要素に反復します。
これら 2 つの操作を考えると、1000 万番目の要素を取得したい場合、できることは 1 つだけです。1000 万回繰り返すことです。これには時間がかかります。
を「スライス」することはありませんEnumerator
。Enumerator
列挙します。それでおしまい。
さて、あなたが発見したように、別の問題があります: Ruby のコレクション操作は型を保存しません。どのタイプのコレクションを呼び出してmap
も、常に同じタイプ、つまり完全に実現された具体的な strict を返しselect
ます。これは、ほとんどの言語でほとんどのコレクション フレームワークが機能する方法です。たとえば、.NET では、すべてのコレクション操作が returnです。これは、これらのメソッドのほとんどがmixin に共通の実装を 1 つしか持たないためです。take
Array
IEnumerable
Enumerable
Smalltalk は例外ですが、別の問題があります。コレクション操作は、すべてのコレクション タイプで重複します。collect:
すべてのコレクション タイプには、などの実質的なコピー アンド ペーストの実装がほとんどない独自のものがあります。このコードの重複は維持が難しく、独自のコレクションをフレームワークselect:
に統合したい人にとっては大きな負担となります。Ruby では簡単です。implement とmixinを実行すれば完了です。each
Enumerable
注: Ruby 1.9 の時点で、実際にはその重複がいくつかあります。 は、実際には ではなく を返すHash
独自のバージョンを実装しています。そのため、コードの重複だけでなく、インターフェイスの非対称性も生じています。select
Hash
Array
select
Array
Hash
Scala 2.8 のコレクション フレームワークは、コードの重複なしに型を保持するコレクション操作を提供する方法を誰かが見つけた初めての例です。しかし、Ruby のコレクション フレームワークは Scala 2.8 より 15 年前に設計されたため、その知識を利用することはできません。
Ruby 2.0 にはEnumerator
、すべてのコレクション操作が別の lazy を返す lazy がありEnumerator
ます。しかし、それはここでは役に立ちません: 唯一の違いは、怠惰な人が実際に値Enumerator
を取得するまで 1,000 万回の反復を遅らせることです。print
他に方法がないため、1,000 万回の反復を実行する必要があります。
スライスが必要な場合は、 などのスライス可能なデータ構造が必要ですArray
。