tutorial - coffeescript vs javascript
Análisis estático de Coffeescript/Comprobación estática de tipos-Obstáculos (2)
Esta respuesta es un poco un volcado de cerebro ya que también estoy interesado en esto. Espero eso ayude.
Utilizo Google Closure Compiler para analizar de forma estática el código que genera CoffeeScript. Tiene un analizador de estática realmente bueno, y no estoy seguro si hay una buena razón para reinventar la rueda aquí. La forma más fácil es simplemente escribir las anotaciones a mano:
###*
* @param {number} x
* @param {number} y
* @return {number}
###
adder = (x, y) -> x + y
Es un poco detallado, pero, por otro lado, está tomando prestadas las habilidades de análisis estático del compilador de cierre, que es realmente poderoso y es capaz de verificar mucho. De hecho, escribo anotaciones de tipo de una manera un poco más concisa, luego tengo un script para volver a escribir el archivo de café. Mi código termina pareciéndose a esto:
#! {number} x {number} y @return {number}
adder = (x, y) -> x + y
Estoy seguro de que puedes ver que el reescritor es bastante sencillo.
Una nota rápida antes de seguir adelante. Asegúrese de compilar su código con -b
(pelado) si lo está ejecutando a través del compilador de cierre. El compilador de cierre es bastante bueno, pero no es lo suficientemente inteligente como para hacer un análisis de flujo de datos. CoffeeScript envuelve su código en una función anónima por defecto, lo que hará que el compilador se dispare.
Otra opción en el mismo camino (esto rompería la compatibilidad con CoffeeScript, pero sería mucho más genial) sería hacer que el compilador de Café compile algo como esto:
adder = (number x, number y): number -> x + y
en JS así:
/***
* @param {number} x
* @param {number} y
* @return {number
*/
var adder = function(x, y) {
return x + y;
};
que luego podría incluirse en el compilador de cierre en una compilación: si no hubiera errores, el compilador podría eliminar todos los comentarios.
De hecho, este tipo parecía estar haciendo exactamente esto. Lamentablemente, su trabajo parece estar en un estado incompleto.
En todos estos casos, diferimos el trabajo duro, la comprobación de tipos estática, al compilador de cierre. Si no quieres hacer esto, lo entendería, pero sería difícil convencerme de que vale la pena construir una nueva herramienta de análisis estático desde cero. :)
EDITAR un año más tarde: acabo de usar mecanografía estos días. :)
Creo que Coffeescript es un lenguaje impresionante! Estaba buscando algunos proyectos / problemas / características que agreguen Static Analysis a Coffeescript. Sin embargo, después de algunas búsquedas, encontré que las preguntas frecuentes sobre Coffeescript y esta página sugieren que el análisis estático podría no ser viable.
Me preguntaba si hay un problema fundamental en la implementación del análisis estático / comprobación de tipos estáticos en Coffeescript, ¿por qué algo de este tipo no existe ya en el compilador?
Además, ¿es algo que no es posible hacer para verificaciones no triviales pero podría funcionar solo para un análisis directo? Cuando digo directamente me refiero a verificar cosas triviales, como si el usuario ha definido una función dos veces con el mismo nombre (en una clase) o en el nivel superior (o quizás en el nivel superior en una colección de archivos .coffee relacionados) .
Apreciaría si alguien pudiera señalar algunos ejemplos que muestren por qué implementar el análisis estático / la comprobación de tipos no es sencillo / posible / vale la pena dedicar tiempo.
¡Muchas gracias!
No soy un experto en CoffeeScript, por lo que esta podría ser la respuesta completamente errónea, pero básicamente se reduce a esto: CoffeeScript es un lenguaje muy expresivo, con la mayoría de la semántica determinada dinámicamente (y posiblemente casos extraños). Esto contrasta mucho con lenguajes como Standard ML, que tienen una semántica mucho más estrictamente definida. En general, el análisis estático en lenguajes de orden superior se considera muy difícil. Es decir, el análisis estático en programas reales de orden superior (Haskell, ML, especialmente javascript debido a cosas como eval) es difícil porque el flujo de control es mucho más flexible. De hecho, las soluciones de análisis estático para lenguajes de orden superior solo se han explorado en los últimos veinte años. (Notablemente, vea el artículo de Matt Might sobre una descripción de estilo de tutorial de CFA ).
Básicamente, las razones son las siguientes:
- Para realizar el análisis , debe lidiar con el problema de la semántica expresiva que viene del control de flujo que se obtiene al atacar funciones de orden superior.
- Para escribir , normalmente estos idiomas tienen un conjunto de tipos mucho más rico que están disponibles. Por ejemplo, hay situaciones muy típicas en las que si intenta asignar un tipo estático a una variable en Ruby (como en C, Java, ML, etc.) obtiene un error, pero debido a que ciertas rutas de su programa nunca son ejecutado, todo está bien. Junto con eso, otros lenguajes como Ruby agregan una gran cantidad de conversiones de tipos implícitas que realmente se usan para hacer una programación genial. El trabajo notable en esta área con el que estoy familiarizado (análisis dinámico de tipos estáticos para Ruby) proviene de algunas de las personas con las que trabajo, pero ciertamente hay otros ejemplos.
- Básicamente, el lenguaje se usa de una manera mucho más dinámica , con una semántica mucho más expresiva , y razonar sobre eso estáticamente es mucho más difícil y propenso a ser impreciso. El frente básico para abordar esto (en estos días) está empezando a parecer híbrido: puede analizar estáticamente una parte de un programa y, además, es necesario que el programador le dé algunos casos de prueba para hacer algún tipo de análisis refinado.
Espero que esto responda un poco a sus preguntas, una vez más, lo siento, no puedo abordar directamente las preocupaciones directas de su pregunta en relación con CoffeeScript, pero en este momento hay mucho trabajo en el análisis de cosas como JavaScript. Notaré que algunos de los problemas reales con Javascript provienen de su extraña semántica, la herencia prototípica es difícil de razonar, ¡y especialmente eval()
! Por lo general, los análisis de programas para estos idiomas imponen ciertas restricciones (por ejemplo, ¡eliminar completamente la evaluación) para hacer el análisis más factible!