Escribir programas en lenguajes dinámicos que van más allá de lo que permite la especificación

StackOverflow https://stackoverflow.com/questions/1811198

  •  06-07-2019
  •  | 
  •  

Pregunta

Con el crecimiento de los lenguajes tipados dinámicamente, ya que nos dan más flexibilidad, existe la muy probable probabilidad de que las personas escriban programas que van más allá de lo que permite la especificación.

Mi pensamiento fue influenciado por esta pregunta, cuando leí la respuesta de bobince: Una pregunta sobre los métodos de corte y empalme de JavaScript

La idea básica es que splice , en Javascript, se especifica para usarse solo en ciertas situaciones, pero se puede usar en otras, y no hay nada que el lenguaje pueda hacer para detener ya que el lenguaje está diseñado para ser extremadamente flexible.

A menos que alguien lea la especificación y decida adherirse a ella, estoy bastante seguro de que hay muchas violaciones de este tipo.

¿Es esto un problema, o una extensión natural de escribir lenguajes tan flexibles? ¿O deberíamos esperar que herramientas como JSLint ayuden a ser la policía de especificaciones?

Me gustó una respuesta en esta pregunta, que la implementación de python es la especificación. Tengo curiosidad por saber si eso está realmente más cerca de la verdad para este tipo de idiomas, que básicamente, si el idioma le permite hacer algo, entonces está en la especificación. ¿Existe una especificación de lenguaje Python?

ACTUALIZACIÓN:

Después de leer un par de comentarios, pensé en verificar el método de empalme en la especificación y esto es lo que encontré, en la parte inferior de la página 104, http://www.mozilla.org/js/language/E262-3.pdf , por lo que parece que puedo usar el empalme en La variedad de niños sin violar la especificación. Simplemente no quiero que la gente se atasque en mi ejemplo, pero espero que considere la pregunta.

    The splice function is intentionally generic; it does not require that its this value be an Array object. 
Therefore it can be transferred to other kinds of objects for use as a method. Whether the splice function 
can be applied successfully to a host object is implementation-dependent.

ACTUALIZACIÓN 2: No me interesa que se trate de javascript, sino de flexibilidad y especificaciones del lenguaje. Por ejemplo, espero que las especificaciones de Java especifiquen que no puedes poner código en una interfaz, pero usando AspectJ lo hago con frecuencia. Esto es probablemente una violación, pero los escritores no predijeron AOP y la herramienta era lo suficientemente flexible como para ser doblada para este uso, así como la JVM también es lo suficientemente flexible para Scala y Clojure.

¿Fue útil?

Solución

Creo que este tipo de flexibilidad es una ventaja siempre que sus métodos estén diseñados en torno a interfaces bien definidas en lugar de algún tipo externo artificial de "tipo" metadatos La mayoría de las funciones de matriz solo esperan un objeto con una propiedad de longitud. El hecho de que todos puedan aplicarse genéricamente a muchos tipos diferentes de objetos es una bendición para la reutilización de código.

El objetivo de cualquier diseño de lenguaje de alto nivel debe ser reducir la cantidad de código que debe escribirse para hacer las cosas, sin dañar demasiado la legibilidad. Cuanto más código se tenga que escribir, más errores se introducirán. Los sistemas de tipo restrictivo pueden ser (si no están bien diseñados), una mentira generalizada en el peor de los casos, una optimización prematura en el mejor de los casos. No creo que los sistemas de tipo demasiado restrictivos ayuden a escribir programas correctos. La razón es que el tipo es simplemente una afirmación, no necesariamente basada en evidencia.

Por el contrario, los métodos de matriz examinan sus valores de entrada para determinar si tienen lo que necesitan para realizar su función. Este es el tipeo de patos, y creo que esto es más científico y `` correcto '', y da como resultado un código más reutilizable, que es lo que desea. No desea un método que rechace sus entradas porque no tienen sus papeles en orden. Eso es comunismo.

Otros consejos

Si un idioma se escribe estática o dinámicamente es realmente una pequeña parte del problema aquí: uno estáticamente escrito puede hacer que sea ligeramente más fácil para el código hacer cumplir sus especificaciones, pero marginalmente es la palabra clave aquí. Solo " diseño por contrato " - un lenguaje que le permite establecer explícitamente condiciones previas, condiciones posteriores e invariantes, y imponerlas - puede ayudarlo a protegerse contra los usuarios de sus bibliotecas descubriendo empíricamente con qué se librará exactamente la biblioteca, y tomando aproveche esos descubrimientos para ir más allá de sus intenciones de diseño (posiblemente limitando su libertad futura para cambiar el diseño o su implementación). Y "diseño por contrato" no es compatible con los idiomas principales: Eiffel es el más cercano a eso, y pocos lo llamarían "corriente principal" hoy en día, presumiblemente porque sus costos (principalmente, inevitablemente, en tiempo de ejecución) no parecen estar justificados por sus ventajas. " El argumento x debe ser un número primo " ;, " el método A debe haberse llamado previamente antes de que el método B pueda llamarse " ;, " el método C ya no se puede invocar una vez que el método D se ha llamado " ;, y así sucesivamente - los tipos típicos de restricciones que desearía establecer (y ha aplicado de manera implícita, sin tener que gastar un tiempo considerable de programación y verificación de energía para ellos) simplemente no se prestan bien para enmarcarse en el contexto de lo poco que el compilador de un lenguaje estáticamente tipado puede imponer.

No creo que su pregunta realmente tenga mucho que ver con la escritura dinámica vs. estática. Realmente, puedo ver dos casos: por un lado, hay cosas como el dispositivo de Duff que Martin Clayton mencionó; ese uso es extremadamente sorprendente la primera vez que lo ve, pero está explícitamente permitido por la semántica del lenguaje. Si hay un estándar, ese tipo de lenguaje puede aparecer en ediciones posteriores del estándar como un ejemplo específico. No hay nada de malo en esto; de hecho, pueden (a menos que se usen en exceso) ser un gran impulso para la productividad.

El otro caso es el de la programación para la implementación. Tal caso sería un abuso real, proveniente de la ignorancia de un estándar, o la falta de un estándar, o tener una sola implementación, o múltiples implementaciones que tienen semántica variable. El problema es que el código escrito de esta manera es, en el mejor de los casos, no portátil entre implementaciones y, en el peor de los casos, limita el desarrollo futuro del lenguaje, por temor a que agregar una optimización o una característica rompa una aplicación importante.

Me parece que la pregunta original es un poco no segregadora. Si la especificación permite explícitamente un comportamiento particular (como DEBE, MAYO, DEBE O DEBERÍA) entonces cualquier compilador / intérprete que permita / implemente el comportamiento es, por definición, compatible con el lenguaje. Esta parece ser la situación propuesta por el OP en la sección de comentarios: la especificación de JavaScript supuestamente * dice que la función en cuestión PUEDE usarse en diferentes situaciones y, por lo tanto, está explícitamente permitida.

Si, por otro lado, un compilador / intérprete implementa o permite un comportamiento que está expresamente prohibido por una especificación, entonces el compilador / intérprete opera, por definición, fuera de la especificación.

Todavía hay un tercer escenario, y un término asociado, bien definido, para aquellas situaciones en las que la especificación no define un comportamiento: indefinido. Si la especificación no especifica realmente un comportamiento dada una situación particular, entonces el comportamiento no está definido, y el compilador / intérprete puede manejarlo intencionalmente o no. Entonces es responsabilidad del desarrollador darse cuenta de que el comportamiento no es parte de la especificación y, si elige aprovechar el comportamiento, la aplicación del desarrollador depende de la implementación particular. El intérprete / compilador siempre que la implementación no tenga la obligación de mantener el comportamiento oficialmente indefinido más allá de la compatibilidad con versiones anteriores y cualquier compromiso que el productor pueda hacer. Además, una iteración posterior de la especificación del lenguaje puede definir el comportamiento previamente indefinido, haciendo que el compilador / intérprete (a) no cumpla con la nueva iteración, o (b) salga con un nuevo parche / versión para cumplir, romper versiones anteriores.

* " supuestamente " porque no he visto la especificación, yo mismo. Voy por las declaraciones hechas, arriba.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top