¿Existe algún mecanismo para hacer que el lenguaje de programación sea más estable (compatible) para los cambios?

14

Hay una gran cantidad de lenguajes de programación. Algunos de ellos crecen y se vuelven muy populares. La gente usa tales idiomas cada vez más a menudo. El fundador de dicho lenguaje (u organización / comunidad fundadora) puede intentar implementar cambios para mejorar el idioma. Pero a veces es difícil hacer algunos cambios debido a la compatibilidad con versiones anteriores y cosas tan feas ya han existido en el lenguaje durante años, y son utilizadas por muchos usuarios.

¿Hay algún principio o paso arquitectónico, durante la fase de diseño del lenguaje, que pueda ayudar a hacerlo más estable para que los diseñadores del lenguaje no tengan tanto miedo de romper la compatibilidad con versiones anteriores?

Viacheslav Kondratiuk
fuente
2
la estabilidad del lenguaje excluye hacer cualquier tipo de cambios importantes. ¿Puedes aclarar tu pregunta?
Simon Bergot
Más estable significa para mí que suceden menos cambios (con suerte porque no son necesarios), exactamente lo contrario de los cambios incompatibles con versiones anteriores. ¿En qué estás interesado o estás preguntando sobre ambos semi-independientemente?
@Simon cómo diseñar un lenguaje que cuando intentas agregar una nueva característica no tienes miedo de frenar la comparabilidad
Viacheslav Kondratiuk
@delnan digamos, ambos.
Viacheslav Kondratiuk
@viakondratiuk No tener miedo no es algo que el diseño del lenguaje pueda cambiar. Una mejor pregunta podría ser "¿Cómo diseñar un lenguaje para que agregar nuevas funciones no provoque cambios importantes ?".
svick

Respuestas:

6

La estabilidad del lenguaje no es una decisión técnica. Es un contrato entre el autor del idioma y los usuarios.

El autor anuncia una versión dada como más o menos estable. Cuanto menos estable es un idioma, más cambios puede hacer el autor. Cada usuario interesado en el idioma puede decidir si quiere invertir tiempo en él para aprender nuevas funciones o desarrollar aplicaciones que podrían estar dañadas por la actualización del próximo mes.

El uso de un lenguaje inestable puede ser interesante porque le interesa un nuevo concepto, o si desea ayudar dando su opinión. Si es una empresa, es posible que prefiera esperar a que una tecnología sea más estable antes de invertir su tiempo en ella. Le importa más cosas como el tiempo de comercialización y la experiencia del usuario.

Así que este es un problema de comunicación y confianza. Mira el desarrollo del lenguaje óxido. Son muy claros sobre lo que están cambiando y lo que están guardando. Cuando quieren retrasar una decisión sobre una característica dada, usan lo que llaman una puerta de características. Por otro lado, el equipo angular enfrentó mucha ira por su anuncio 2.0 porque los cambios fueron más grandes de lo esperado.

Incluso las bibliotecas de autor tienen que comunicar sobre la estabilidad de sus apis. Casi cualquier tecnología utilizada por otras personas tiene que lograr un equilibrio entre estabilidad y perfección. Un fabricante de automóviles no puede cambiar la posición de los pedales, y un diseñador de computadoras portátiles no inventará un nuevo diseño de teclado por la misma razón: no está ayudando a sus usuarios si no puede tomar una decisión sobre la forma en que usarán su producto.

Simon Bergot
fuente
5
  • Tenga en cuenta que los idiomas cambian a lo largo de su vida, independientemente de qué tan bien se pueda diseñar por adelantado. En lugar de tratar de enviar de inmediato el lenguaje más increíble del mundo, primero intenta ser útil y extensible. Un lenguaje mediocre que realmente puedo usar vale más que cualquier maravilloso lenguaje de programación que solo existe en teoría.
  • Considere las facilidades para hacer que la sintaxis sea extensible, por ejemplo, macros. Las macros no son automáticamente algo bueno y pueden ser demasiado poderosas. Algunos idiomas tienen una sintaxis muy flexible desde el principio, lo que reduce la necesidad de macros. Un par de escenarios a considerar:

    • ¿Puedo presentar un nuevo operador como |> sin abandonar el idioma? ¿Puedo elegir precedencia y asociatividad para este operador?
    • ¿Cuánta ceremonia tengo que pasar para una función en línea / lambda / cierre?
    • ¿Puedo usar la sintaxis del lenguaje existente para implementar una sintaxis de bucles foreach? Por ejemplo, Ruby y Scala pueden hacer esto a través de su sintaxis de llamada de método flexible con lambdas.
  • Considere las instalaciones para mantener la semántica extensible. Las necesidades comunes son:

    • Sobrecarga del operador, donde los tipos definidos por el usuario pueden asignar su propio significado a los operadores existentes. Esto hace que un lenguaje sea mucho más agradable en aplicaciones pesadas en matemáticas.
    • Sobrecarga literal. ¿Puedo hacer que los literales de cadena sean de mi propio tipo de cadena? ¿Puedo hacer que todos los literales numéricos en el alcance actual sean bignums?
    • Protocolos de metaobjetos. Si el lenguaje no tiene rasgos, ¿puedo implementarlos dentro del sistema de objetos actual? ¿Puedo implementar un orden de resolución de método diferente? ¿Puedo cambiar la forma en que se almacenan los objetos o cómo se envían los métodos?
  • Tener pruebas de regresión. Mucha prueba. No solo escrito por los diseñadores de idiomas, sino también por los usuarios. Al agregar una función se rompen estas pruebas, sopesar cuidadosamente los beneficios de esa función contra el beneficio de la compatibilidad con versiones anteriores.
  • Versión tu idioma. No solo en su documentación, sino también en el código fuente mismo. Una vez que haga eso, la única parte de su idioma que no puede cambiar es esta sintaxis de pragma de versión. Ejemplos: Raqueta le permite especificar un dialecto. Perl lo permite use v5.20, lo que habilita todas las características incompatibles con versiones anteriores de Perl v5.20. También puede cargar funciones individuales explícitamente como use feature 'state'. Similar: Pythonfrom __future__ import division .
  • Considere diseñar su idioma de manera que resulte en pocas palabras reservadas. El hecho de que classintroduzca una clase no implica que no podría tener una variable local llamada class. En la práctica, esto da como resultado palabras clave que introducen declaraciones de variables o métodos, en contra de la tradición tipo C de usar nombres de tipos para introducir declaraciones. Otra alternativa es usar sigilos para usted $variables, como en Perl y PHP.

Parte de esta respuesta está influenciada por el discurso de Guy Steele "Growing a Language" (1998) ( pdf ) ( youtube ).

amon
fuente
Algunos de sus puntos hablan de que los programadores que usan el lenguaje pueden extenderlo y otros hablan de los diseñadores del lenguaje que pueden extenderlo. ¿No son los dos en su mayoría no relacionados? Y creo que la pregunta es hablar de este último tipo.
svick
@svick La idea es que un lenguaje es tan extensible por los usuarios finales que se puede hacer mucha extensión y experimentación sin cambiar el idioma en sí. Los protocolos de metaobjetos, la sobrecarga del operador y los sistemas macro son una forma de dejar la puerta abierta para cambios posteriores. Cualquier cosa que se implemente a través de estas puertas no rompe fundamentalmente el lenguaje. Desafortunadamente, estas puertas podrían tener que rediseñarse más tarde. Ahí es donde entra en juego la premisa de la respuesta de Simon: antes de prometer estabilidad, realice una prueba beta para averiguar si su idioma realmente funciona.
amon
1

Creo que un paso bastante importante es promover un administrador de paquetes que también pueda administrar la versión del lenguaje en sí.

Por ejemplo, uso SBT para Scala o Leiningen para Clojure. Ambos me permiten declarar qué versión del idioma quiero usar, por proyecto . Por lo tanto, es bastante fácil comenzar proyectos ecológicos en la última versión del lenguaje, mientras se actualizan los proyectos existentes a un ritmo más cómodo, si es que alguna vez lo hace.

Por supuesto, dependiendo del idioma, esto aún puede dejarlo con la necesidad de esperar a que las bibliotecas relevantes se porten a la versión que necesita (esto sucede, por ejemplo, en Scala), pero de todos modos facilita las cosas.

Andrea
fuente
con el corolario de que la mayor parte del lenguaje posible debe definirse en paquetes / módulos importables como sea posible
jk.
Sí, pero no necesariamente. Por ejemplo, el compilador de Scala está escrito en Scala, pero cuando configura la versión de Scala en sbt, solo se obtiene como un Jar y se utiliza para compilar sus fuentes. Incluso si fuera un binario opaco, eso también funcionaría. Ahora, hay razones para definir la mayor cantidad de lenguaje posible que debe definirse en paquetes importables, pero están cubiertos en la respuesta de amon
Andrea