Paul Graham: Brevedad = Fuerza

Hoy en HackerNews planteamos una discusión sobre el artículo de Paul Graham en 2002 y decidimos resucitar su traducción de la inexistencia.

imagen


"La cantidad de significado comprimido en un espacio pequeño
por signos algebraicos, es otra circunstancia que facilita
los razonamientos a los que estamos acostumbrados a continuar con su ayuda".
- Charles Babbage (1791-1871)


En una discusión sobre el artículo LL1 Revenge en la lista de correo LL1, Paul Prescod expresó una idea que no se me olvida.

El objetivo de Python es la regularidad y la legibilidad, pero no la brevedad.

A primera vista, un lenguaje de programación probablemente no debería pretender serlo. Según tengo entendido, brevedad (concisión, concisión, compacidad) = fuerza. Y si es así, haciendo una sustitución, obtenemos:

El objetivo de Python es la regularidad y la legibilidad, pero no el poder.

lo cual, a su vez, no es un compromiso muy bueno (si es realmente un compromiso), que vale la pena hacer. Parece que si dices: el objetivo del lenguaje Python no es ser un lenguaje de programación efectivo.

¿Brevedad = fuerza? Esta parece una pregunta importante, tal vez la pregunta más importante para aquellos involucrados en el desarrollo de idiomas. Todavía no estoy seguro de que la respuesta sea simplemente "sí", pero para empezar, esta es una buena hipótesis.

Hipótesis


Mi hipótesis es que la brevedad es poder, o están tan cerca que, con la excepción de los casos patológicos, puede tomarlos por algo idéntico.

La brevedad, me parece, es para lo que se crean los lenguajes de programación. Las computadoras serían igualmente felices si recibieran instrucciones directamente en lenguaje de máquina. Creo que la razón principal por la que vamos a desarrollar lenguajes de alto nivel es para obtener la ventaja de expresar (y más importante, pensar) diez líneas en un lenguaje de alto nivel, lo que requeriría 1000 líneas de código de máquina. En otras palabras, el objetivo principal de los lenguajes de alto nivel es acortar el código fuente.

Si el código fuente más corto es el propósito de los lenguajes de alto nivel, y la fuerza de algo es una medida de qué tan bien se logra el objetivo, entonces la fuerza del lenguaje de programación es cuánto reduce sus programas.

Por el contrario, un lenguaje que no hace que sus programas sean más pequeños hace un mal trabajo de un lenguaje de programación, al igual que un cuchillo que corta mal o una impresión ilegible.

Métrica


¿Y en qué sentido es menos? La medida más común del tamaño del código fuente es el número de líneas. Pero esta medida es común solo por la simplicidad de la medición, y no creo que nadie crea que es una buena prueba del tamaño del programa. Los idiomas tienen diferentes convenciones sobre lo que se puede colocar en una línea; bastantes líneas en C pueden tener solo uno o dos separadores.

Otra prueba simple es el número de caracteres en el programa, pero este no es demasiado bueno; Algunos idiomas (como Perl) tienen identificadores más cortos que otros.

Creo que la mejor medida del tamaño de un programa puede ser el número de elementos, donde el elemento es algo que podría convertirse en un vértice separado en el árbol de origen. El nombre de una variable o función es un elemento; un número entero o un número real es un elemento; un segmento literal de texto es un elemento; un elemento de una directiva de patrón o formato es un elemento. Hay casos límite (¿es "-5" uno o dos elementos?), Pero creo que la mayoría de ellos son iguales en todos los idiomas, por lo que no afectarán demasiado la comparación.

Esta medida debe concretarse, y puede requerir interpretación adicional en el caso de algunos lenguajes específicos, pero me parece que está tratando de medir lo correcto: el número de partes del programa. El árbol de origen es lo que dibuja en su mente para representar el programa y, por lo tanto, el tamaño de este árbol es proporcional a la cantidad de trabajo necesario para escribirlo o leerlo.

Diseño


Esta medida nos permitiría comparar diferentes idiomas, pero este no es, al menos para mí, su valor básico. Y el valor de la prueba de brevedad es una guía para diseñar idiomas. La comparación de idiomas más útil es comparar dos variaciones posibles del mismo idioma. ¿Qué puedo hacer en el idioma para acortar los programas?

Si la carga conceptual de un programa es proporcional a su complejidad, y un programador determinado puede soportar una cierta carga conceptual, entonces esto es lo mismo que preguntar: ¿cómo pueden ayudar los programadores a hacer más? Y esto, me parece, es lo mismo que preguntar: ¿cómo diseñar un buen lenguaje?

(Por cierto, la falsedad de este ya barbudo dicho "todos los idiomas son equivalentes" se ve más claramente cuando se diseñan idiomas. Cuando creas un nuevo idioma, constantemente comparas dos idiomas, uno en el que haría X, y el otro en el que no, para que decida qué es mejor. Si fuera una pregunta sin sentido, podría lanzar una moneda.)

Tener un objetivo de brevedad parece ser una buena manera de encontrar nuevas ideas. Si encuentra una manera de acortar los programas, esto no es una coincidencia: probablemente haya encontrado una nueva abstracción útil. Incluso podría escribir un programa que obtenga fragmentos repetidos en el código fuente. Se pueden encontrar nuevas ideas entre los idiomas que tienen fama de ser concisos: Forth, Joy, Icon.

Comparación


El primero en escribir sobre estas cosas fue, hasta donde yo sé, Fred Brooks con su libro Mythical Man-Month. Escribió que los programadores generan la misma cantidad de código independientemente del idioma. Cuando lo leí por primera vez a los 20 años, fue una gran sorpresa, y me pareció que esto tenía enormes consecuencias. Esto significa que (a) la única forma de escribir programas más rápido es usar un lenguaje más corto, y (b) el que se haya molestado en hacer esto preguntará a los competidores que no lo hacen.

La conjetura de Brooks, si es cierta, puede ser la esencia misma de la piratería. Desde entonces, a lo largo de los años, he prestado atención a todo lo que sería relevante para el tema: desde estudios teóricos hasta historias sobre proyectos individuales. No vi nada que contradiga esta hipótesis.

Pero no he visto ninguna evidencia clara, y no espero verlas. Estudios como la comparación de los lenguajes de programación Lutz Prekelt, aunque producen los resultados esperados, tienden a utilizar tareas que son demasiado pequeñas para una prueba significativa. La mejor prueba para un idioma es lo que sucede en los programas escritos en un mes. Y si está convencido, como yo, de que el objetivo principal de los idiomas es ser un buen idioma en el que piensan (en lugar de un idioma en el que dan instrucciones a la computadora después de que lo piense), entonces la prueba real para el idioma es ¿Qué novedades puedes escribir sobre él? Por lo tanto, comparar idiomas basados ​​en una especificación predefinida es algo incorrecto.

La verdadera prueba para el idioma es qué tan bien puede encontrar y resolver nuevos problemas en él, pero no las tareas formuladas por otra persona. Estos son criterios diferentes. En el arte, las herramientas como el bordado y el mosaico funcionan bien si sabe de antemano lo que desea obtener, pero absolutamente indecente si no lo sabe. Si desea revelar una imagen en el proceso de escribir una imagen (lo que debe hacer al revelar cosas tan complejas como, por ejemplo, la imagen de una persona), debe usar una herramienta más flexible como lápiz, tinta o pinturas al óleo. Por supuesto, los tapices y los mosaicos se hacen así: primero se crea una imagen, y luego solo se copia.

Esto significa que es poco probable que tengamos una comparación adecuada de la fuerza relativa de los lenguajes de programación. Tendremos comparaciones exactas, pero no correctas. En particular, es probable que los estudios dirigidos explícitamente a las comparaciones de idiomas usen tareas pequeñas y necesariamente usarán un conjunto predefinido de tareas, y por lo tanto tenderán a subestimar los idiomas más poderosos.

Es probable que los informes en esta área, aunque serán menos precisos que los estudios "científicos", sean más significativos. Por ejemplo, Ulf Wieger de Ericsson realizó un estudio y llegó a la conclusión de que Erlang es 4-10 veces más corto que C ++, y que la velocidad de desarrollo de software es proporcionalmente mayor:

La comparación de proyectos internos en Ericsson revela una productividad similar en líneas de código por hora, incluidas todas las fases de desarrollo, independientemente del lenguaje utilizado (Erlang, PLEX, C, C ++ o Java). Diferencias de idioma: solo en la cantidad total de código fuente.


Este estudio también indica claramente que no aparece en el libro de Brooks (ya que solo midió líneas de código depurado): los programas escritos en lenguajes más potentes tienden a contener menos errores. Esto ya es suficiente, y probablemente en tareas como los conmutadores de red, esto es más importante que el rendimiento del programador.

Sabores


Al final, puedes confiar en tu instinto. ¿Qué es la programación en este lenguaje? Creo que para crear un mejor lenguaje deberías volverse hipersensible a lo bien que el lenguaje te permite pensar en él, y luego elegir o desarrollar un lenguaje que te parezca más adecuado. Si alguna propiedad del idioma es inconveniente o restrictiva, no se preocupe, lo sabrá.

Pero tal hipersensibilidad hará que los lenguajes torpes se vuelvan insoportables para usted. Encuentro que la programación en lenguajes que no tienen macros es insoportablemente restrictiva, como si alguien acostumbrado a la tipificación dinámica considerara insoportablemente restrictivo el retorno a los idiomas, donde los tipos deberían describirse para cada variable declarada y es imposible declarar una lista que consta de elementos diferentes tipos.

Y no estoy solo. Conozco a muchos hackers de Lisp con quienes sucedió algo similar. De hecho, la medida más precisa de la fuerza relativa de un lenguaje de programación podría ser la proporción de programadores que conocen un idioma determinado que realizarán cualquier trabajo en el que se deba usar este idioma, independientemente del área temática.

Limitaciones


Probablemente, muchos hackers saben lo que se siente cuando el lenguaje parece restrictivo. Esta es probablemente la misma sensación que cuando te quedas atascado en un atasco en la calle por el que quieres conducir y tienes que hacer un largo desvío. Quiere decir algo y el lenguaje no le permite hacer esto.

De hecho, un lenguaje limitante no es un lenguaje sucinto. El problema no es que no puedas expresar algo, sino que el desvío que este lenguaje te obliga a hacer es demasiado largo. Haga este experimento mental: desea escribir algún tipo de programa, y ​​el lenguaje no le permite hacerlo de la manera que planeó, sino que lo hace más corto. Al menos para mí esto no sería demasiado restrictivo. Como si un policía lo dirigiera desde un atasco hacia una carretera más corta en lugar de un desvío largo. ¡Guauu!

Me parece que la sensación de limitación básicamente (¿en un 90 por ciento?) Proviene del hecho de que estás obligado a hacer que el programa sea más largo en el idioma en el que estás escribiendo, en comparación con el idioma en el que piensas. La limitación es básicamente una brevedad insuficiente, por lo que cuando un idioma parece ser limitante, significa que no es lo suficientemente corto.

Legibilidad


La cita con la que comencé también menciona otras dos cualidades: regularidad y legibilidad. Realmente no entiendo qué es la regularidad y cuáles son los beneficios del código legible y regular en comparación con el código legible. Pero creo que sé lo que se entiende por legibilidad, y también me parece que esto tiene que ver con la brevedad.

Aquí debemos tener cuidado con los conceptos de legibilidad de una sola línea de código y la legibilidad del programa en su conjunto. Solo lo último es importante. Estoy de acuerdo en que una línea en BASIC es más legible que una en Lisp, pero un programa escrito en BASIC tendrá más líneas que el mismo programa escrito en Lisp. Leer el programa BASIC requerirá más esfuerzo.

esfuerzo total = esfuerzo para leer una línea * número de líneas


No estoy tan seguro de que la legibilidad sea proporcional a la brevedad, pero definitivamente la brevedad es un factor en la legibilidad (consulte la fórmula anterior). Por lo tanto, no tiene sentido decir que el propósito del lenguaje es la legibilidad, pero no la brevedad.

Para un usuario que ve un idioma determinado por primera vez, la legibilidad línea por línea significa que este idioma le parecerá inofensivo. Por lo tanto, la legibilidad línea por línea puede ser una buena decisión de marketing, aunque es una mala decisión de diseño. Es isomorfo con respecto al método de pago a plazos: en lugar de sentirse intimidado por un depósito grande, le ofrece al comprador un pequeño pago mensual. El pago en partes no es rentable para él, así como la legibilidad línea por línea, para el programador. El comprador debe hacer muchos pagos pequeños, así como el programador debe leer muchas líneas legibles por separado.

Esta relación existía incluso antes del advenimiento de los lenguajes de programación. Si lee novelas y artículos de periódicos, su primera experiencia leyendo un artículo en matemáticas puede ser aterradora: leer una página lleva media hora. Sin embargo, estoy seguro de que el problema no está en la notación, como podría parecer a primera vista. Un artículo en matemáticas es difícil de leer porque las ideas en sí mismas son complejas. Si expresa las mismas ideas en prosa (como lo hicieron los matemáticos antes de pensar en una breve notación), leerlas no sería más fácil, porque esta sola página se convertiría en un libro completo.

En que grado


Algunos no estaban de acuerdo con la idea de brevedad = fuerza. Creo que, en lugar de discutir si esto es así, sería más útil preguntar en qué medida la brevedad es poder. Porque está claro que la brevedad es uno de los principales propósitos de los lenguajes de programación. Y si no, ¿cuál es su propósito y cuán importantes son esas otras funciones?

Propongo esto para no hacer la discusión más civilizada. Realmente quiero saber la respuesta. ¿Cuándo, si esto sucede, el lenguaje se vuelve lo suficientemente conciso?

La hipótesis con la que comencé fue que, a excepción de algunos casos patológicos, la brevedad es idéntica a la fuerza. Quise decir que serán idénticos en cualquier lenguaje desarrollado por alguien, pero si alguien quiere crear un lenguaje específicamente para refutar esta hipótesis, entonces probablemente funcionará. Pero tampoco estoy muy seguro de eso.

Idiomas pero no programas


Debe quedar claro que estamos hablando de la brevedad de los idiomas, no de los programas individuales. Por supuesto, algunos programas se pueden escribir muy estrictamente.

Escribí sobre esto en el libro "Acerca de Lisp". Para que la macro se justifique a sí misma, debe ahorrar muchas veces más espacio en relación con su propia longitud. Si alguna macro voluminosa guarda diez líneas de código cada vez que la usa, y la macro en sí misma consta de diez líneas, obtendrá ahorros en líneas si la usa más de dos veces. Pero esto sigue siendo un mal movimiento, ya que las definiciones de macro son más difíciles de leer que el código normal. Es posible que deba usar la macro 10 o 20 veces antes de que mejore la legibilidad.

Estoy seguro de que en cualquier idioma tales compromisos son posibles (aunque sospecho que las apuestas se plantean en idiomas fuertes). Todos los programadores han visto código que se acorta extremadamente debido a las dudosas técnicas de programación.

Por lo tanto, es indiscutible, al menos para mí, que los programas pueden ser lo suficientemente concisos. La pregunta es, ¿pueden los idiomas mismos ser cortos? ¿Pueden los lenguajes obligar a los programadores a escribir brevemente (en elementos) a costa de la legibilidad?

Una razón por la que es difícil imaginar un lenguaje demasiado conciso es que si hay una forma demasiado compacta de expresar algo, entonces probablemente habrá una forma más larga. Por ejemplo, si le parece que el uso de macros o funciones de alto nivel en Lisp es demasiado denso, puede escribir código que sea isomorfo a Pascal. Si no desea expresar el factorial en el lenguaje de Arc como una llamada a una función de alto nivel,

(rec zero 1 * 1-)

entonces también puede escribir una definición recursiva:

(rfn fact (x) (if (zero x) 1 (* x (fact (1- x)))))

aunque no puedo dar ejemplos tan inmediatamente, me interesa la pregunta: ¿puede el lenguaje ser demasiado corto? ¿Hay algún idioma que te obligue a escribir código ilegible? Si alguien tiene algún ejemplo, me alegraría verlo.

(Recuerde: estoy interesado en los programas que tienen una alta densidad de acuerdo con la medida de los "elementos" descritos anteriormente, pero no los programas que son cortos solo porque se pueden omitir los separadores y todo tiene nombres que tienen un solo carácter).

Se publicó por primera vez aquí. .




imagen
Aprenda los detalles de cómo obtener una profesión solicitada desde cero o subir de nivel en habilidades y salario tomando los cursos en línea de SkillFactory:




All Articles