Si tratta di un follow-up alla mia precedente question per quanto riguarda le Seq
iter
e map
funzioni del modulo di essere molto più lento rispetto agli equivalenti modulo Array
e List
.Perché alcune funzioni del modulo Seq sono ottimizzate mentre altre non erano in F #?
Guardando alla fonte, posso vedere che alcune funzioni come isEmpty
e length
esegue un controllo di tipo molto semplice per ottimizzare per gli array e le liste prima di ricorrere all'utilizzo di 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
Nel caso del iter
lo stesso approccio può essere fatto per migliorare notevolmente le sue prestazioni, quando ho shadowed la funzione iter
ha presentato aumenti significativi rispetto alla versione built-in:
[<CompiledName("Iterate")>]
let iter f (source : seq<'T>) =
checkNonNull "source" source
use e = source.GetEnumerator()
while e.MoveNext() do
f e.Current;
mio la domanda è, dato che alcune delle funzioni nel modulosono state ottimizzate per l'uso con specifici tipi di raccolta (array, lista < T>, ecc.) come mai altre funzioni come iter
e nth
non sono state operative timized in un modo simile?
Inoltre, nel caso della funzione map
, come indicato da @mausch, non è possibile utilizzare un approccio simile a Enumerable.Select
(vedere di seguito) e creare iteratori specializzati per diversi tipi di raccolta?
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);
}
Molte grazie in anticipo.
Non sono sicuro che avrai una risposta decente a una domanda "perché" come questa qui; la mia migliore _guess_ è semplicemente la mancanza di tempo per lo sviluppatore. – ildjarn