これは、モジュールのおよび関数がおよびモジュールの同等物に比べてはるかに遅いという以前の質問へのフォロー アップです。Seq
iter
map
Array
List
ソースを見ると、 や などの一部の関数isEmpty
はlength
、 を使用する前に配列とリストを最適化するために非常に単純な型チェックを実行することがわかりますIEnumerator
。
[<CompiledName("IsEmpty")>]
let isEmpty (source : seq<'T>) =
checkNonNull "source" source
match source with
| :? ('T[]) as a -> a.Length = 0
| :? list<'T> as a -> a.IsEmpty
| :? ICollection<'T> as a -> a.Count = 0
| _ ->
use ie = source.GetEnumerator()
not (ie.MoveNext())
[<CompiledName("Length")>]
let length (source : seq<'T>) =
checkNonNull "source" source
match source with
| :? ('T[]) as a -> a.Length
| :? ('T list) as a -> a.Length
| :? ICollection<'T> as a -> a.Count
| _ ->
use e = source.GetEnumerator()
let mutable state = 0
while e.MoveNext() do
state <- state + 1;
state
同じアプローチの場合iter
、パフォーマンスを大幅に向上させることができます。関数をシャドウするiter
と、組み込みバージョンよりも大幅に向上しました。
[<CompiledName("Iterate")>]
let iter f (source : seq<'T>) =
checkNonNull "source" source
use e = source.GetEnumerator()
while e.MoveNext() do
f e.Current;
私の質問は、Seq
モジュール内の一部の関数が特定のコレクション型 (配列、list< T> など) で使用するために最適化されていることを考えると、どうして や などの他の関数がiter
同様nth
の方法で最適化されなかったのでしょうか?
また、map
関数の場合、@mausch が指摘したように、同様のアプローチを採用してEnumerable.Select
(以下を参照)、さまざまなコレクション タイプに特化したイテレータを作成することはできませんか?
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
{
if (source == null)
throw Error.ArgumentNull("source");
if (selector == null)
throw Error.ArgumentNull("selector");
if (source is Enumerable.Iterator<TSource>)
return ((Enumerable.Iterator<TSource>) source).Select<TResult>(selector);
if (source is TSource[])
return (IEnumerable<TResult>) new Enumerable.WhereSelectArrayIterator<TSource, TResult>((TSource[]) source, (Func<TSource, bool>) null, selector);
if (source is List<TSource>)
return (IEnumerable<TResult>) new Enumerable.WhereSelectListIterator<TSource, TResult>((List<TSource>) source, (Func<TSource, bool>) null, selector);
else
return (IEnumerable<TResult>) new Enumerable.WhereSelectEnumerableIterator<TSource, TResult>(source, (Func<TSource, bool>) null, selector);
}
よろしくお願いします。