parsing - traduccion - El uso de la palabra "redundancia" por Walter Bright... o "¿Qué diablos significa eso?"
syntax error traduccion (8)
Así que estoy leyendo esta entrevista con Walter Bright sobre el lenguaje D en Bitwise ( http://www.bitwisemag.com/copy/programming/d/interview/d_programming_language.html ), y me encuentro con esta cita realmente interesante sobre el lenguaje. análisis
Sin embargo, desde una perspectiva teórica, poder generar un buen diagnóstico requiere que haya redundancia en la sintaxis. La redundancia se utiliza para hacer una suposición de lo que se pretendía, y cuanta más redundancia, más probable es que la suposición sea correcta. Es como el idioma inglés: si escribimos mal una y otra vez, o si faltara una palabra, la redundancia nos permite adivinar correctamente el significado. Si no hay redundancia en un idioma, cualquier secuencia aleatoria de caracteres es un programa válido.
Y ahora estoy tratando de averiguar qué diablos quiere decir cuando dice "redundancia".
Apenas puedo envolver mi cabeza alrededor de la última parte, donde menciona que es posible tener un lenguaje en el que "cualquier secuencia aleatoria de caracteres sea un programa válido". Me enseñaron que hay tres tipos de errores: sintáctico, de ejecución y semántico. ¿Hay idiomas en los que los únicos errores posibles sean semánticos? ¿Es asamblea así? ¿Qué pasa con el código de máquina?
entonces cualquier secuencia aleatoria de caracteres es un programa válido.
Aunque no del todo "cualquier secuencia aleatoria es válida", considere las expresiones Perl y regulares. Su muy corta sintaxis hace que sea más fácil para los personajes inválidos pasar un análisis sintáctico y semántico.
Bueno, para usar un ejemplo de C # (ya que no sé D). Si tiene una clase con un método abstracto, la clase debe estar marcada como abstracta:
public abstract class MyClass
{
public abstract MyFunc();
}
Ahora, sería trivial que el compilador marque automáticamente MyClass como abstracto (así es como C ++ lo maneja), pero en C #, debe hacerlo explícitamente, para que sus intenciones sean claras.
Lo mismo ocurre con virtual
métodos virtual
. En C ++, si declara virtual en una clase base, un método es automáticamente virtual en todas las clases derivadas. En C #, sin embargo, el método debe estar explícitamente marcado como override
, para que no haya confusión sobre lo que deseaba.
Creo que hablaba de estructuras sintácticas en el lenguaje y cómo se pueden interpretar. Como ejemplo, considere la humilde declaración "si", representada en varios idiomas.
En bash (shell script), se ve así:
if [ cond ]; then
stmts;
elif [ other_cond ]; then
other_stmts;
else
other_other_stmts;
fi
en C (con estados individuales, sin llaves):
if (cond)
stmt;
else if (other_cond)
other_stmt;
else
other_other_stmt;
Puede ver que en bash, hay una estructura sintáctica mucho más que la de if. De hecho, todas las estructuras de control en bash tienen sus propios delimitadores de cierre (por ejemplo, if/then/fi
, for/do/done
, case/in/esac
, ...), mientras que en C la llave se utiliza en todas partes. Estos delimitadores únicos desambiguan el significado del código y, por lo tanto, proporcionan un contexto desde el cual el intérprete / compilador puede diagnosticar las condiciones de error e informarlas al usuario.
Hay, sin embargo, una compensación. Los programadores generalmente prefieren la sintaxis concisa (a la C, Lisp, etc.) a la sintaxis detallada (a la Pascal, Ada, etc.). Sin embargo, también prefieren mensajes de error descriptivos que contengan números de línea / columna y soluciones sugeridas. Estos objetivos, por supuesto, están en desacuerdo entre sí: no puedes tener tu pastel y comértelo también (al menos, manteniendo la implementación interna del compilador / intérprete simple).
Creo que un mejor ejemplo de redundancia es algo como int a[10] =
. En este punto, el compilador sabe lo que debería venir después, un inicializador int array, y puede mostrar un mensaje de error apropiado si lo que sigue no es un inicializador int array. Si la sintaxis del lenguaje dijera que cualquier cosa podría seguir int a[10]
, sería mucho más difícil para el compilador resolver problemas con uno.
El lenguaje ensamblador (la mayoría de los lenguajes ensambladores, de todos modos) no es así en absoluto: tienen una sintaxis bastante rígida y la mayoría de las cadenas aleatorias se diagnostican como errores.
El código de máquina está mucho más cerca Como no hay traducción del código de "fuente" a "objeto", todos los errores son semánticos, no sintácticos. La mayoría de los procesadores tienen varias entradas que rechazarían (por ejemplo, ejecutar una captura / interrupción de "código de operación incorrecto"). Podría argumentar que en algunos casos esto sería sintáctico (por ejemplo, un código de operación que no se reconoció en absoluto) donde otros son semánticos (por ejemplo, un conjunto de operandos que no se permitieron para esa instrucción).
Para aquellos que lo recuerdan, TECO fue famoso (¿notorio?) Por asignar algún significado a casi cualquier entrada posible, por lo que fue casi de la misma manera. Un desafío interesante fue averiguar qué pasaría si escribiera (por ejemplo, su nombre).
Esto significa que la sintaxis contiene más información de la necesaria para codificar un programa de trabajo. Un ejemplo son los prototipos de funciones. Como nos muestra K&R C, son redundantes porque el compilador puede simplemente permitir que la persona que llama introduzca los argumentos que desee, y luego dejar que la función extraiga los argumentos correctos. Pero C ++ y otros lenguajes los obligan, porque ayudan al compilador a verificar que está llamando a la función de la manera correcta.
Otro ejemplo es el requisito de declarar variables antes de usarlas. Algunos idiomas tienen esto, mientras que otros no lo hacen. Es claramente redundante, pero a menudo ayuda a prevenir errores (por ejemplo, errores de ortografía, utilizando una variable que se ha eliminado).
Me centraré en por qué (creo) Walther Bright piensa que la redundancia es buena. Tomemos XML como ejemplo. Este fragmento de código:
<foo>...</foo>
tiene redundancia, la etiqueta de cierre es redundante si usamos S-Expressions en su lugar:
(foo ...)
Es más corto, y el programador no tiene que escribir foo
más a menudo de lo necesario para dar sentido a ese fragmento. Menos redundancia. Pero tiene desventajas, como muestra un ejemplo de http://www.prescod.net/xml/sexprs.html :
(document author: "[email protected]"
(para "This is a paragraph " (footnote "(better than the one under there)" ".")
(para "Ha! I made you say /"underwear/"."))
<document author="[email protected]">
<para>This is a paragraph <footnote>(just a little one).</para>
<para>Ha! I made you say "underwear".</para>
</document>
En ambos, falta la etiqueta final / un paren de cierre para la nota al pie. La versión xml no es válida en cuanto el analizador vea </para>
. La S-Expression one solo es inválida al final del documento, y solo si no tiene un parén de cierre innecesario en otro lugar. Por lo tanto, la redundancia ayuda, en algunos casos, a entender lo que quiso decir el escritor (y señalar los errores en su forma de expresar eso).
nglsh nclds ll srts de xtr ltrs t mk it ezr t leen