Ésta es una continuación de mi anterior question con respecto a los módulos de Seq
iter
y map
funciones siendo mucho más lento en comparación con los Array
y List
equivalentes módulo.¿Por qué se optimizan algunas funciones en el módulo Seq mientras que otras no están en F #?
En cuanto a la fuente, puedo ver que algunas funciones, como isEmpty
y length
realiza una comprobación de tipo muy simple para optimizar para las matrices y listas antes de recurrir al uso de 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
En el caso de la iter
el mismo enfoque se puede hacer para mejorar notablemente su rendimiento, cuando shadowed la función iter
que presenta mejores resultados que la versión incorporada:
[<CompiledName("Iterate")>]
let iter f (source : seq<'T>) =
checkNonNull "source" source
use e = source.GetEnumerator()
while e.MoveNext() do
f e.Current;
Mi La pregunta es, dado que algunas de las funciones en el módulo Seq
se optimizaron para su uso con tipos de colección específicos (matrices, lista < T>, etc.) cómo otras funciones tales como iter
y nth
no fueron opcionales timized de manera similar?
Además, en el caso de la función map
, como señaló @mausch, ¿no es posible utilizar un enfoque similar al Enumerable.Select
(ver a continuación) y crear iteradores especializados para diferentes tipos de colecciones?
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);
}
Muchas gracias de antemano.
No estoy seguro de que pueda obtener una respuesta decente a una pregunta 'por qué' aquí; mi mejor _guess_ es simplemente la falta de tiempo del desarrollador. – ildjarn