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 (comefmapin 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:)