¿Cómo afecta un sistema de tipo estático al diseño de un lenguaje basado en prototipos?

15

El artículo de Wikipedia sobre lenguajes basados ​​en prototipos contiene el siguiente párrafo:

Casi todos los sistemas basados ​​en prototipos se basan en lenguajes interpretados y tipados dinámicamente. Sin embargo, los sistemas basados ​​en lenguajes tipados estáticamente son técnicamente factibles.

¿De qué manera un sistema de tipo estático impone restricciones o introduce complejidad en el lenguaje basado en prototipos, y por qué hay más lenguajes de prototipos de tipo dinámico?

Joe
fuente
2
+1 y favorito: lo he estado reflexionando durante bastante tiempo, y no encontré ningún problema extraordinariamente difícil con un sistema de tipo estructural . De hecho, esto me molesta tanto que me quieren por delante y tratar de crear un lenguaje basado en prototipos de tipo estático sólo para ver qué problemas hay ...
Solo estoy comenzando ese proceso por la misma razón :)
Joe

Respuestas:

6

El borde entre un tipo fundamental y un objeto es borroso y, a menudo, se introduce artificialmente. Por ejemplo, en C, una estructura es solo un conjunto de registros, solo un tipo no objeto derivado. En C ++, una estructura es una clase con todos los campos públicos, un objeto. Aún así, C ++ es casi totalmente compatible con C ... el borde es realmente suave aquí.

Para la programación basada en prototipos, debe tener objetos mutables en tiempo de ejecución. DEBEN ser de tipo suave porque cada uno cambia en tiempo de ejecución, una clase de un tipo cambia a otra, su tipo cambia.

Sin embargo, puede mantener los tipos no objetos fundamentales y derivados como estáticos. Pero esto introduce una extraña disparidad, los objetos son de tipo suave, los no objetos son de tipo estático, y se debe establecer una barrera dura entre los dos. ¿Deberías poder transformar una estructura? ¿Una cuerda? ¿Debe Number ser una clase o un tipo fundamental, o un conjunto de tipos fundamentales, int / float / bignum / etc?

Es más natural y fácil de aprender, usar y escribir para tener este uniforme, todos los tipos son mutables o ningún tipo es mutable en tiempo de ejecución. Si declaras que solo un tipo (Objeto) es mutable, terminas con dolores de cabeza y problemas de ambos mundos.

De tipo estático es:

  • más fácil de implementar
  • más rápido / más eficiente
  • mas seguro
  • más fácil de mantener / documentar grandes sistemas debido a la abstracción.

De tipo dinámico es:

  • más rápido para escribir,
  • mas conciso
  • lenguaje más fácil de aprender
  • más indulgente por errores de diseño.

Al mezclar los dos, sacrificas mucho.

  • La implementación se vuelve más difícil que cualquiera de las dos anteriores.
  • la velocidad depende si usa los tipos suaves o no ... Si lo hace, es bajo, si no lo hace, ¿por qué elegir el idioma?
  • type safety está fuera de la ventana para todos los tipos de objetos.
  • Seguir cómo un tipo se transforma en otro es una tarea bastante difícil. Documentarlo, muy difícil.
  • Todavía necesita hacer toda la contabilidad con tipos fundamentales, lo que mata la concisión y la velocidad de escritura.
  • La complejidad del lenguaje es mayor (más difícil de aprender) que cualquiera de los "específicos",
  • "perdonar" a un tipo dinámico se reemplaza por la tendencia a algunos errores muy complicados en los tipos de atributos que no coinciden.
SF.
fuente
1
Recuerde proporcionar un ejemplo de por qué los objetos deben ser "mutables" (supongo que se refiere a la adición y eliminación de atributos, no a cambiarlos, ya que eso generalmente no está relacionado con la escritura).
@delnan: en realidad no, en la programación basada en prototipos puedes cavar en las entrañas de un objeto como mejor te parezca, eliminar, agregar, reemplazar, cubrir, tanto métodos como atributos en una instancia en vivo. Ese es el punto y un reemplazo muy conveniente y flexible para modificar objetos a través de reglas rígidas de herencia clásica. Si un idioma usa una clase como tipo, no puede modificar su estructura sobre la marcha si el tipo no es suave.
SF.
1
No lo creo. Según la misma lógica, se podría argumentar que la programación basada en clases necesita las mismas libertades que los lenguajes dinámicos basados ​​en clases lo permiten. No, los prototipos estáticos con un sistema de tipo estructural anotarían los objetos con una lista de sus miembros y recursivamente sus tipos, y verificarían estáticamente que estos miembros existen (y tienen el tipo correcto) al exigir que todos los miembros se den al crear el objeto o que estén presentes en el prototipo y simplemente no incluye una forma de eliminar miembros. El resultado todavía me parece bastante prototipo y garantiza que cada miembro esté presente en todo momento.
@delnan: Acabas de describir la herencia clásica a través de la composición. Sí, parece bastante prototipo y es una forma (muy nerf) de hacer programación basada en prototipos en un lenguaje clásico de modelo de herencia. Simplemente despoja a pb.p del 90% de la diversión, eliminando sus mayores ventajas (y al mismo tiempo eliminando los mayores peligros). Sí, en la antigua analogía de los disparos con los pies, pb.p con todas las funciones te ayudará a disparar ambas piernas con una cuchara de té. Si no te gusta este tipo de poder, será mejor que te quedes con la herencia clásica.
SF.
1
Confundes "dinámico" con "prototipos". Estas libertades que no se combinan bien con los sistemas de tipo estático no son características de los prototipos, son características del dinamismo. Por supuesto, agregar tipeo estático los impide, pero no son parte de los prototipos (eso es IMGO, principalmente la falta de clases a favor de la clonación de objetos para actuar como padres). Ese dinamismo es ortogonal a los prototipos. Todos los lenguajes de prototipos populares los incluyen, pero son independientes de los prototipos como se indicó anteriormente. Considere este fragmento en un lenguaje ficticio: pastebin.com/9pLuAu9F . ¿Cómo es que no son prototipos?
3

La dificultad es bastante sencilla de ver: tomando la vista de los objetos como diccionarios de métodos, o como cosas que responden a los mensajes, observe lo siguiente sobre los lenguajes OO de tipo estático comunes:

  • Todas las claves / mensajes del diccionario generalmente se declaran por adelantado, utilizando identificadores declarados estáticamente.

  • Ciertos conjuntos de mensajes se declaran por adelantado, y los objetos se asocian a estos conjuntos para determinar a qué mensajes responden.

  • Las relaciones de inclusión de un conjunto de mensajes que son un subconjunto de otro se declaran estática y explícitamente; no declarados pero los subconjuntos lógicos no son válidos.

  • La verificación de tipo intenta garantizar que todos los mensajes se envíen solo a los objetos que responden a ellos.

Cada uno de estos conflictos en cierta medida con un sistema basado en prototipos:

  • Los nombres de los mensajes se pueden declarar por adelantado, en forma de "átomos" o cadenas internados o cualquier otra cosa, pero poco más; La plasticidad de los objetos significa que asignar tipos a métodos es incómodo.

  • Podría decirse que la característica esencial de un sistema basado en prototipos es que los conjuntos de mensajes se definen por lo que responde un objeto, en lugar de lo contrario. Sería razonable asignar alias a combinaciones particulares en tiempo de compilación, pero los conjuntos de mensajes determinados en tiempo de ejecución deben ser posibles.

  • El impacto real de los dos éxitos anteriores se relaciona con relaciones de inclusión, donde las declaraciones explícitas son completamente inviables. La herencia en el sentido de subtipo nominal estático es antitético a un sistema basado en prototipos.

Lo que nos lleva al punto final, que en realidad no queremos cambiar. Todavía nos gustaría asegurarnos de que los mensajes solo se envíen a los objetos que responden a ellos. Sin embargo:

  • No podemos saber estáticamente qué mensajes se pueden agrupar.
  • No podemos saber qué agrupaciones son subconjuntos de otras.
  • No podemos saber qué agrupaciones son posibles.
  • Ni siquiera podemos especificar qué tipo de argumentos se envían junto con un solo mensaje.
  • Básicamente, hemos descubierto que no podemos especificar mucho de nada en el caso totalmente general.

Entonces, ¿cómo se puede solucionar esto? Limite la generalidad completa de alguna manera (lo cual es desagradable y puede eliminar rápidamente cualquier beneficio de usar un sistema basado en prototipos en primer lugar), o haga que el sistema de tipos sea mucho más fluido y exprese restricciones en lugar de tipos exactos .

El sistema de tipos basado en restricciones conduce rápidamente a la noción de subtipado estructural , que en un sentido muy laxo puede considerarse como el equivalente estático del "tipeo de pato". Los mayores obstáculos aquí son que tales sistemas son mucho más complicados para la verificación de tipos y son menos conocidos (lo que significa poco trabajo previo para estudiar).

En resumen: es posible, es más difícil de hacer que un sistema de tipo estático nominal o un sistema dinámico basado en metadatos de tiempo de ejecución y, por lo tanto, pocas personas se molestan.

CA McCann
fuente
1

Creo que una forma de lograr un lenguaje basado en prototipos de tipo estático sería basar el lenguaje en Plantillas y Conceptos.

Los conceptos fueron una vez una característica planificada para C ++ 0x. El código genérico en las plantillas de C ++ ya está de facto "tipado estáticamente". La idea de Concepts es poder decir algunas cosas sobre los miembros requeridos y las características de los tipos, sin requerir o implicar un modelo de herencia de clase subyacente a esa relación (porque tenía que funcionar con el código de plantilla existente que ya estaba "tipado estáticamente") )

En un lenguaje basado desde cero en Plantillas y Conceptos, serían los Conceptos los que están basados ​​en prototipos, y las Plantillas lo liberarían de preocuparse por cualquier modelo de clase que pueda o no usarse para implementar los tipos de valores.

Además de los trucos de usar la compilación por etapas para permitir que el lenguaje sea su propio metalenguaje, estas derivaciones prototípicas de Conceptos serían necesariamente inmutables una vez creadas. Sin embargo, la objeción de que eso no está basado en prototipos es una pista falsa. Simplemente sería un lenguaje funcional. Al menos se ha intentado un lenguaje dinámico basado en prototipos que también es funcional .

Dennis Ferron
fuente