2009-09-13 11 views
10

Estoy buscando en LINQ y el lenguaje de consulta aparece (al menos en la superficie) para ser nada más que una implementación de mapas y/o listas de comprensión como se encuentran en Haskell y otros lenguajes FP (particularmente la generalización de 'mapa' y 'para' en Scala). ¿Es esto correcto? ¿Hay más en la sintaxis que esto? Desde el tono sin aliento del libro que estoy leyendo ("Essential LINQ"), parece que hay algo nuevo o innovador aquí.¿Cuánto hay para LINQ?

Existe todo el back-end, el pipeline, los árboles y tipos de expresiones de primer orden, etc. para implementar LINQ, pero mi pregunta es sobre el lenguaje de consulta en sí.

Saludos

Joe

Respuesta

25

Hablando funcionalmente, LINQ no es más que una simplificación sintáctica para expresar mónadas. Linq to Objects (Lista de comprensiones - incluso esto ya sería extremadamente útil), de lo que ha estado hablando, es solo una posible aplicación de esto (similar a List-Monad en Haskell).

Si se escribe

from x in expr1 
from y in expr2 
select x + y 

No es más que

do 
    x <- expr1 
    y <- expr2 
    return $ x + y 

en Haskell.

Lo concreto que se hace depende de LINQ proveedores definidos por el usuario (extensión-Métodos) de los cuales Linq.Enumerable es sólo una aplicación que implica IEnumerable s.

Al proporcionar uno, puede crear una semántica LINQ completamente nueva para sus tipos.

Ejemplo: Dado un tipo Option para los cálculos que pueden fallar (valores que aceptan valores anulables), se podría definir un proveedor de Linq para consultar sobre ellos.

public static class MaybeExtensions 
{ 
public static Option<T> ToMaybe<T>(this T value) 
{ 
    return Option<T>.Some(value); 
} 

public static Option<U> SelectMany<T, U>(
    this Option<T> m, 
    Func<T, Option<U>> k) 
{ 
    return !m.IsNone ? Option<U>.None : k(m.Value); 
} 

public static Option<V> SelectMany<T, U, V>(
    this Option<T> m, 
    Func<T, Option<U>> k, 
    Func<T, U, V> s) 
{ 
    return m.SelectMany(x => k(x).SelectMany(y => s(x, y).ToMaybe())); 
} 
} 

Esto sería ahora nos permitirá escribir dicho código:

var sum = from x in ReadNumber("x") 
      from y in ReadNumber("y") 
      select x + y; 

El cálculo sólo devolverá un valor si todos los cálculos tuvieron éxito y de lo contrario se producirá un error en la primera fallar uno.

En combinación con los árboles de expresión, LINQ puede ser extremadamente potente y le permite expresar -

  1. base de datos de accesos
  2. asíncrono flujo Programm
  3. quizá, Mónadas
  4. listas por comprensión
  5. recursiva Analizadores de descenso
  6. Continuaciones
  7. Mini-idiomas
  8. cálculos paralelos (PLINQ)

Algunos enlaces:

Combinado con los combinadores de punto fijo, Linq proporciona un mini-lenguaje funcional completo (Linq raytracer).

Tenga en cuenta que Scala y F # ambos tienen conceptos similares en para-comprensiones y expresiones de cálculo que ambos son abstracciones monádicos:

Scala:

for (x <- expr1 
    y <- expr2) yield x + y 

F #:

monad { 
    let! x = expr1 
    let! y = expr2 
    return x + y 
} 
+0

Gracias por la información. Voy a investigar esas pistas. – Joe

+0

Realmente, muy buen resumen con un ejemplo agradable y fácil de comprender. +1 –

+0

Continuando en el enlace raytracer, aquí está el mismo raytracer implementado por completo en una sola declaración LINQ: http://tirania.org/blog/archive/2007/Nov-16.html – JulianR

4

Además de la lectura de un libro sobre el tema, ya no utiliza LINQ? Descubrí que es un gran ahorro de tiempo en mi trabajo diario de programación. Para mí, es el siguiente paso de la abstracción, que se puede utilizar para combinar diferentes fuentes de datos como XML o SQL y trabajar con ellos en el mismo "idioma".

Además, recomiendo este interview with Anders Hejlsberg sobre programación funcional y LINQ.

+0

Gracias por la respuesta y el enlace, lo leeré. Sí, lo he usado un poco (y creo que es muy útil), pero lo usé de la misma manera que lo he estado usando en Scala. Hice la pregunta debido a las similitudes y me pregunté qué tan profundo iban. – Joe

5

La falta de aliento probablemente esté destinada a todas esas cosas "obvias", algunas de las cuales (como los árboles de expresión) son realmente excelentes. El lenguaje es solo un medio de acceso; ¿Te emociona la palabra clave throw o la funcionalidad que expone?

+0

No quise decir que las "cosas obvias" fueran obvias, simplemente que se reconoció, ¡pero no es el centro de mi pregunta! Quizás lo formulé un poco mal. – Joe

+0

Otros, por favor, lea el comentario de Ben M a la luz de mi edición de la pregunta. – Joe

2

LINQ se inspiró por HaskellDB, como Erik Meijer ha declarado numerosas veces, por ejemplo en Confessions of a Used Programming Language Salesman (Getting the Masses Hooked on Haskell), por lo que no es en sí un concepto nuevo. Usar el mismo lenguaje para consultar diferentes fuentes es hasta cierto punto innovador, aunque el hecho de que el modelo anidado-relacional cubra XML, objetos y bases de datos relacionales ha sido mostrado anteriormente por investigadores. Para mí, lo más genial es que se ha incorporado a un lenguaje popular, de propósito general y principalmente orientado a objetos, algo que no se ha hecho antes.

Scala IMHO tiene la capacidad de incorporar algo similar. Hasta ahora, para Scala tenemos Stefan Zeiger's ScalaQuery y Daniel Spiewak's ScalaQL, que siguen los pasos de LINQ.

+0

Gracias por los enlaces, se ven muy interesante. – Joe

3

El núcleo de LINQ, la sintaxis de la consulta, no es en realidad de gran alcance.Se trata simplemente de algunos muy literales traducciones, a métodos y lambdas - por lo

var qry = from x in src 
      where x.Foo == "foo" 
      select x.Bar; 

es literalmente:

var qry = src.Where(x => x.Foo == "foo").Select(x => x.Bar); 

se sabe nada acerca de los métodos de extensión (aunque son los más comunes (pero no implementación solamente), y nada sobre Expression etc. El número de palabras clave (y por lo tanto el número de implementaciones de método requeridas) no es enorme. Jon una vez intentó implementarlos todos en 1 hora (en una presentación en vivo). Él no lo hizo tan mal ;-P


Tal vez la parte más impresionante de LINQ es la expresión árbol apoyo que se requiere para permitir LINQ para ser utilizado con bases de datos - es decir, la expresión lambda que puede ser compilado ya sea a un delegado o a un modelo de objetos que representa el código escrito. Curiosamente, esta misma idea se refleja en la forma en que la resolución DLR funciona en 4.0.

+0

Una perspectiva muy útil. Gracias por aclararlo. – Joe

Cuestiones relacionadas