Motivazione
L'idea principale è esplorare e comprendere i limiti di quanto si può andare lontano con i primitivi LINQ di base (Select, SelectMany, Concat, ecc.). Queste primitive possono essere tutte considerate operazioni funzionali su un tipo di sequenza teorica. Prendendo esempi da Haskell:
-
Select
"alza" una funzione nella sequenza (comefmap
in Haskell) -
Concat
è composizione -
Aggregate
è il catamorfismo (piega) del tipo di sequenza
-
SelectMany
'estrae' le informazioni dalla sequenza (il collegamento Monad, l'operazione>>=
) - ecc. (e sono sicuro che ci sono migliori astrazioni per quanto sopra)
Quindi la domanda è se le operazioni di sequenza di base (Enumerable) in C # siano sufficienti per costruire una sequenza infinita. Più concretamente è il seguente problema:
Problema
Sono curioso di sapere se c'è un modo per implementare qualcosa di equivalente al seguente, ma senza usare yield
:
IEnumerable<T> Infinite<T>()
{
while (true) { yield return default(T); }
}
È possibile fare causa usando solo gli operatori LINQ integrati?
La risposta breve è che teoricamente sì, ma praticamente non a causa di come viene implementato Linq (causando overflow dello stack).
Ecco perché qui ci sono regole meno restrittive:
Regole
In alternativa, una domanda meno restrittiva andrebbe secondo le regole
- Non puoi utilizzare direttamente la parola chiave
yield
- Utilizza solo C # direttamente - nessun codice IL, nessuna costruzione dinamica ecc.
- Puoi utilizzare solo la lib di base di .NET (solo
mscorlib.dll
,System.Core.dll
? non sai che altro includere). Tuttavia, se trovi una soluzione con alcuni degli altri assembly .NET (WPF ?!), sono anche interessato. - Non implementare IEnumerable o IEnumerator.
Note
Un esempio di definizione teoricamente corretta è:
IEnumerable<int> infinite = null;
infinite = new int[1].SelectMany(x => new int[1].Concat(infinite));
Questo è " correct " ma colpisce StackOverflowException dopo 14399 iterazioni tramite enumerable (non proprio infinito).
Penso che non ci sia modo di farlo a causa del compilatore del C # mancanza di ottimizzazione della ricorsione della coda . Una prova sarebbe carina:)