2011-09-15 8 views
6

F # 3.0 ha agregado type providers.¿Qué idiomas idioms/paradigmas/características hacen que sea difícil agregar soporte para "tipos de proveedores"?

Me pregunto si es posible agregar esta función de idioma a otros idiomas que se ejecutan en el CLR como C# o si esta característica solo funciona bien en un estilo de programación OO más funcional/menos?

+3

Sería más interesante para preguntar acerca de las características del lenguaje que hace que este tipo de cosas más fáciles de implementar. Y la respuesta es: metaprogramación del tiempo de compilación (como en Lisp, MetaOCAML, Nemerle, Template Haskell, etc.). Me pregunto por qué implementaron proveedores de tipos como primitivos en F #, en lugar de permitir una solución más genérica. Y esta metaprogramación es completamente ortogonal a OO, funcional, imperativa, en absoluto, puedes jugar este juego con cualquier lenguaje posible. –

+0

@ SK-logic: creo que los proveedores de tipos _son_ una forma de metaprogramación de tiempo de compilación. Además, las soluciones "más generales" que elogias tienen su propio conjunto de compensaciones también. Por ejemplo, MetaOCAMl hace que el sistema de tipo sea más complejo al introducir la idea de la puesta en escena (y hasta donde yo sé, permite citar/empalmar/ejecutar solo expresiones, no escribir definiciones). – kvb

+1

@kvb, sí, son de hecho una forma de metaprogramación de tiempo de compilación. Pero preferiría tener una metaprogramación genérica completa en lugar de varias "formas" específicas de ella. Y, sí, MetaOCAML no es ideal; hay formas de hacer lo mismo mucho, mucho más fácilmente. –

Respuesta

7

Como señalan Brian y Tomas, no hay nada particularmente "funcional" en esta característica. Es solo una forma particularmente ingeniosa de proporcionar metadatos al compilador.

El equipo de diseño de C# ha estado dando vueltas a ideas como esta durante mucho tiempo. Hubo una propuesta unos años antes de unirme al equipo de C# para una función que se llamaría "modelos de tipo" (o algo así) mediante la cual una combinación de documentos XML, esquema XML y código personalizado que ofreciera metadatos de tipo up podría ser utilizado por el compilador de C#. No recuerdo los detalles y nunca llegó a buen término, obviamente. (Aunque influyó en el diseño y la implementación del formato de documento de Visual Studio Tools para Office, en el que estaba trabajando en ese momento)

En cualquier caso, no tenemos planes en el horizonte inmediato para agregar tal función a C#, pero estamos mirando con gran interés para ver si hace un buen trabajo resolviendo problemas del cliente en F #.

(Como siempre, las reflexiones de Eric sobre las posibles características futuras de los productos unnannounced y totalmente hipotéticas son para fines de entretenimiento.)

+0

también será interesante cómo funciona para scala (siq) y gosu (ots) ... – soc

+0

Diría que es absolutamente necesario mejorar el modelo de compilación de dependencias. esto es demasiado implícito, y no composable. Supongo que esto obstaculiza una gran evolución que puedo imaginar para su plataforma. – nicolas

5

No veo ninguna razón técnica por la que algo como los proveedores de tipo no se puedan agregar a C# o idiomas similares. La única familia de lenguajes que hacen que sea difícil agregar proveedores de tipos (de manera similar a F #) son lenguajes de escritura dinámica.

Los proveedores de tipo F # se basan en el hecho de que la información de tipo generada por el proveedor se propaga muy bien a través del programa y el editor puede usarlos para mostrar IntelliSense útil. En lenguajes de tipeo dinámico, esto requeriría una compatibilidad IDE más elaborada (y los "proveedores de tipo" para lenguajes dinámicos se reducen a solo IDE o IntelliSense).

¿Por qué se implementan directamente como una característica de F #? Creo que el sistema de metaprogramación tendría que ser realmente complejo (tenga en cuenta que los tipos no son en realidad generados) para soportar esto. Las otras cosas que podrían hacerse al usarlo no contribuirían tanto al lenguaje F # (solo lo harían demasiado complejo, lo cual es algo malo). Sin embargo, podría obtener algo similar si tuviera algún tipo de extensibilidad del compilador.

De hecho, creo que así es como el equipo C# agregará algo así como tipo de proveedores en el futuro (hablaron sobre la extensibilidad del compilador desde hace algún tiempo).

+1

Dudo que un subsistema de metaprogramación pueda ser complejo. De hecho, cualquier lenguaje con una metaprogramación decente es mucho, mucho más simple que un lenguaje monolítico, ya que permite definir características de idioma en una biblioteca en lugar de un núcleo de compilación. Vea cuán pequeño es el lenguaje central de Nemerle, por ejemplo. –

+0

La metaprogramación no es un requisito para eso. – soc

+1

@ SK-logic: tenga en cuenta que la parte meta del programa necesita ser llamada desde el IDE, posiblemente con algunas restricciones de seguridad. Además, no puede simplemente "generar" todos los tipos desde http://www.programmableweb.com/, ya que no tendría suficiente memoria para eso. Necesita generar tipos perezosamente. Todo el meta-sistema todavía tendría que compilarse para .NET ... estoy seguro de que esto requeriría más desarrollo que una versión de F #. –

8

Como dice Tomas, teóricamente es fácil agregar este tipo de característica a cualquier lenguaje estáticamente tipeado (aunque todavía hay mucho trabajo pesado).

No soy un experto en meta-programación, pero @ SK-logic pregunta por qué no un sistema general de metaprogramación en tiempo de compilación en su lugar, y trataré de responder. No creo que pueda lograr fácilmente lo que puede hacer con los proveedores de tipo F # utilizando metaprogramación, porque los proveedores de tipo F # pueden ser perezosos y dinámicamente interactivos en el momento del diseño. Pongamos un ejemplo de que Don ha mostrado una versión demo en uno de sus videos anteriores: un proveedor de tipo Freebase. Freebase es como una wikipedia esquematizada y programable, tiene datos de todo. Por lo que puede llegar a escribir código en la línea de

for e in Freebase.Science.``Chemical Elements`` do 
    printfn "%d: %s - %s" e.``Atomic number`` e.Name e.Discoverer.Name 

o lo que sea (no tengo la improvisada código exacto), pero con la misma facilidad escribir código que obtiene información sobre las estadísticas de béisbol, o cuando los actores famosos tienen estado en instalaciones de rehabilitación de drogas, o un billón de otros tipos de información disponible a través de Freebase.

Desde un punto de vista de implementación, no es factible generar un esquema para toda la Freebase y llevarlo a .NET a-priori; no se puede simplemente hacer un paso de tiempo de compilación al comienzo para configurar todo esto. Usted puede hacer esto para fuentes de datos pequeñas, y de hecho muchos otros proveedores de tipos utilizan esta estrategia, p. un proveedor de tipo SQL se apunta a una base de datos y genera tipos .NET para todos los tipos en esa base de datos. Pero esta estrategia hace no funciona para grandes almacenes de datos en la nube como Freebase, porque hay demasiados tipos interrelacionados (si intenta generar metadatos .NET para toda la Freebase, encontrará que hay tantos millones de tipos (uno de los cuales es ChemicalElement con AtomicNumber y Discoverer y Name y muchos otros campos, pero hay literalmente millones de tales tipos) que necesita más memoria que la disponible para un proceso .NET de 32 bits solo para representar el esquema de tipo completo.

Por lo tanto, la estrategia de proveedor de tipos F # es una arquitectura de API que permite a los proveedores de tipos suministrar información según demanda, ejecutándose en tiempo de diseño dentro del IDE. Hasta que escriba, p. Freebase.Science., el proveedor de tipo no necesita saber acerca de las entidades en las categorías de ciencia, pero una vez que presione . después de Science, el proveedor de tipo puede ir y consultar las API para aprender un nivel más del esquema general, para saber qué categorías existen bajo Science, una de las cuales es ChemicalElements. Y luego, cuando tratas de "rozar" uno de esos, descubrirá que los elementos tienen números atómicos y otras cosas. Por lo tanto, el proveedor de tipo obtiene perezosamente lo suficiente del esquema general para tratar con el código exacto que el usuario escribe en el editor en ese momento. Como resultado, el usuario todavía tiene la libertad de explorar cualquier parte del universo de información, pero cualquier archivo de código fuente o sesión interactiva solo explorará una pequeña fracción de lo que está disponible. Cuando llega el momento de compilar/codegen, el compilador solo necesita generar el código suficiente para acomodar exactamente los bits que el usuario ha usado realmente en su código, en lugar de los bits de tiempo de ejecución potencialmente enormes para permitir la posibilidad de hablar con todo el almacén de datos.

(Tal vez se puede hacer eso con algunas de las instalaciones de los meta-programación de hoy ahora, no sé, pero los que aprendimos en la escuela mucho tiempo atrás no podría haber manejado fácilmente esto.)

+0

+1 para describir la pereza :) – Ankur

+1

¿Entiendo correctamente que se generará información de tipo _only_ para los tipos explícitamente referenciados en el código? ¿Eso significa atravesar recursivamente todo su "universo de datos" es imposible? – Daniel

+1

El proveedor de tipo puede elegir hacer lo que quiera, pero el compilador solo lo instanciará con sus parámetros estáticos y luego lo invocará 'a petición'. Por ejemplo, el proveedor de SQLConnection en el cuadro solo genera el esquema completo como tipos .Net por adelantado, mientras que un proveedor de Freebase claramente debe esperar hasta que el compilador lo llame a petición para hacer una pequeña cantidad de trabajo con cada llamada. – Brian

Cuestiones relacionadas