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.)
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. –
@ 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
@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. –