prefacio
Alguien hoy y conversó con el C # LINQ, LINQ LINQ encuentro Sé que parece como la mayoría de las personas no saben lo mismo, cómo una ley diferente? De hecho, LINQ también se puede utilizar para participar en la programación funcional.
Por supuesto, no quiere decir unas pocas escritura lambda
y similares con el uso de Java como stream
tales, incluso si el llamado LINQ, LINQ es en realidad una otra cosa.
LINQ
En C #, LINQ Creo que hemos visto la siguiente redacción:
IEnumerable<int> EvenNumberFilter(IEnumerable<int> list)
{
return from c in list where c & 1 == 0 select c;
}
Con la sintaxis de LINQ por encima de los implementos de código de una lista de cribado, incluso.
LINQ es sólo un conjunto de herramientas que se utilizan para facilitar la operación de la misma, si queremos que nuestro propio si el tipo de sintaxis de soporte LINQ, entonces tenemos que lograr nuestro tipo IEnumerable<T>
, entonces puede estar tan acostumbrado. . .
Oh, es cierto? Entiendo todo eso. . . . . .
? ? ? Oh, Dios mío, por supuesto que no!
De hecho, LINQ y IEnumerable<T>
no tiene nada que ver! LINQ es sólo un conjunto de extensiones único método, que se compone principalmente de los métodos siguientes:
nombre del método | Descripción del método |
---|---|
Dónde | filtrado de datos |
Seleccionar / SelectMany | proyector de datos |
Join / GroupJoin | conexión de datos |
OrdenarPor / ThenBy / OrderByDescending / ThenByDescending | Ordenación de datos |
Agrupar por | Los paquetes de datos |
...... |
El método anterior corresponde LINQ Palabras clave: where
, select
, join
, orderby
, group
...
Cuando el compilador compila código C # que convertirá LINQ sintaxis de llamadas a métodos de extensión de sintaxis, por ejemplo:
from c in list where c > 5 select c;
Se compila en:
list.Where(c => c > 5).Select(c => c);
Para otro ejemplo:
from x1 in list1 join x2 in list2 on x1.k equals x2.k into g select g.u;
Se compila en:
list1.GroupJoin(list2, x1 => x1.k, x2 => x2.k, (x1, g) => g.u);
Para otro ejemplo:
from x in list orderby x.k1, x.k2, x.k3;
Se compila en:
list.OrderBy(x => x.k1).ThenBy(x => x.k2).ThenBy(x => x.k3);
Una vez más:
from c in list1
from d in list2
select c + d;
Se compila en:
list1.SelectMany(c => list2, (c, d) => c + d);
Parada, parada!
Además, el compilador en tiempo de compilación siempre será primero y luego llamar a la traducción sintaxis LINQ compilado como un método, a continuación, siempre y cuando el nombre del método correspondiente, no significa que usted puede utilizar la sintaxis de LINQ (escape
Así que ya ves este SelectMany
no lo es. . .
SelectMany
es Monad
Oh, Dios mío, nos fijamos en este pobre SelectMany
, esto no Monad
se requiere bind
la función?
Poco a poco las cosas se ponen interesantes de nuevo.
Hemos heredado el espíritu de uno, escribir de nuevo Maybe<T>
.
Maybe<T>
En primer lugar, se escribe una clase abstracta Maybe<T>
.
En primer lugar, tenemos que añadir a un Select
método para la selección de los Maybe<T>
datos, si es T
, entonces un retorno Just<T>
, si es Nothing<T>
, entonces un retorno Nothing<T>
. El equivalente de nuestra returns
función:
public abstract class Maybe<T>
{
public abstract Maybe<U> Select<U>(Func<T, Maybe<U>> f);
}
Entonces nos damos cuenta de nuestra Just
e Nothing
:
public class Just<T> : Maybe<T>
{
private readonly T value;
public Just(T value) { this.value = value; }
public override Maybe<U> Select<U>(Func<T, Maybe<U>> f) => f(value);
public override string ToString() => $"Just {value}";
}
public class Nothing<T> : Maybe<T>
{
public override Maybe<U> Select<U>(Func<T, Maybe<U>> _) => new Nothing<U>();
public override string ToString() => "Nothing";
}
Entonces, tenemos que Maybe
darnos cuenta bind
- que es, al Maybe
añadir un conocido SelectMany
método.
public abstract class Maybe<T>
{
public abstract Maybe<U> Select<U>(Func<T, Maybe<U>> f);
public Maybe<V> SelectMany<U, V>(Func<T, Maybe<U>> k, Func<T, U, V> s)
=> Select(x => k(x).Select(y => new Just<V>(s(x, y))));
}
Hasta ahora, Maybe<T>
conseguido a lo largo! Lo que, en este? ? Entonces, ¿cómo se usa? Momento emocionante que viene!
En primer lugar, creamos unos cuantos Maybe<int>
:
var x = new Just<int>(3);
var y = new Just<int>(7);
var z = new Nothing<int>();
A continuación, se calcularon utilizando el LINQ x + y
, x + z
:
var u = from x0 in x from y0 in y select x0 + y0;
var v = from x0 in x from z0 in z select x0 + z0;
Console.WriteLine(u);
Console.WriteLine(v);
salida:
Just 10
Nothing
Perfecto! El LINQ anteriormente compilado como:
var u = x.SelectMany(_ => y, (x0, y0) => x0 + y0);
var v = x.SelectMany(_ => z, (x0, z0) => x0 + z0);
En este momento, las funciones k
como int -> Maybe<int>
, y la función s
que (int, int) -> int
, además de una función.
Función k
parámetros que no me importa, que se utiliza como selector
, sólo tenemos que generar una marca Maybe<int>
, y luego usar la función s
de los dos int
valores hacemos víbora, y los resultados en un abarrotado Just<int>
dentro de la lata.
Este proceso, si no se producen o bien Nothing
, el resultado es siempre la operación de seguimiento Nothing
, porque Nothing.Select(...)
todavía Nothing
.
Una pequeña extensión
Damos este Maybe<T>
más un Where
:
public abstract class Maybe<T>
{
public abstract Maybe<U> Select<U>(Func<T, Maybe<U>> f);
public Maybe<V> SelectMany<U, V>(Func<T, Maybe<U>> k, Func<T, U, V> s)
=> Select(x => k(x).Select(y => new Just<V>(s(x, y))));
public Maybe<U> Where(Func<Maybe<T>, bool> f) => f(this) ? this : new Nothing<T>();
}
Entonces podemos jugar:
var just = from c in x where true select c;
var nothing = from c in x where false select c;
Console.WriteLine(just);
Console.WriteLine(nothing);
Cuando la condición devuelve Just
, de lo contrario devuelve Nothing
. Por encima de la salida:
Just 3
Nothing
Hay un olor en el interior (escape
posdata
Los siguientes artículos de esta serie serán escritos en la hipoteca, si C # decepcionante que los sindicatos discriminado, Superior Kinded genéricos y tipo de características Clases más, y seguimos.