Conozco el concepto de ortogonalidad, pero desde el punto de vista del lenguaje de programación, ¿hay alguna forma de verificarlo / probarlo?
Por ejemplo, en C #, uno puede usar public
o static
para una firma de método. Puede usar uno o ambos y no interferirían entre sí, por lo que son ortogonales entre sí, ¿verdad?
Mi pregunta es, ¿cómo hago para el resto de características, particularmente características que no están relacionadas entre sí?
¿Todas las características tienen que coexistir / apilarse juntas?
¿Existe un lenguaje de programación que sea 100% ortogonal?
c#
.net
programming-languages
language-design
Joan Venge
fuente
fuente
Respuestas:
No estoy seguro de que la ortogonalidad pueda servir como métrica útil o válida en el caso de lenguajes de alto orden de propósito general como C #, porque requiere la distinción de "operaciones" y "operandos", las pequeñas partes del lenguaje que no son fáciles de entender. distinguible en lenguajes de alto orden como C #.
Mi comprensión de la ortogonalidad se basa en el lenguaje Assembler, donde la ortogonalidad del conjunto de instrucciones de una determinada CPU o microcontrolador en particular indica si hay algunas restricciones en las operaciones realizadas por esta CPU o controlador dependiendo de los tipos de datos. En los primeros tiempos esto era importante porque no todas las CPU admitían operaciones en números fraccionarios o números de diferente longitud, etc.
A este respecto, preferiría comprobar la ortogonalidad del lenguaje intermedio común utilizando el lenguaje Stack Machine como destino para el compilador de C #, no el propio C #.
Si está realmente interesado en la ortogonalidad de C # y no me equivoco aquí (para cualquier propósito) sugeriría buscar algunos algoritmos de programación genética . Puede usarlos para generar diferentes programas a partir del conjunto de palabras clave dado (incluso los que no tienen sentido) y puede verificar automáticamente si son compilables. Esto lo ayudaría a ver automáticamente qué elementos del lenguaje se pueden combinar y derivar algunos aspectos de su métrica de ortogonalidad.
fuente
El término "ortogonalidad" es un término simple para una noción matemática precisa: los términos del lenguaje forman un álgebra inicial (búsquelo en Wikipedia).
Básicamente significa "hay una correspondencia 1-1 entre sintaxis y significado". Esto significa: hay exactamente una forma de expresar las cosas y, si puede poner alguna expresión en un lugar en particular, entonces puede poner cualquier otra expresión allí también.
Otra forma de pensar en "ortogonal" es que la sintaxis obedece al principio de sustitución. Por ejemplo, si tiene una instrucción con un espacio para una expresión, cualquier expresión se puede colocar allí y el resultado sigue siendo un programa sintácticamente válido. Además, si reemplaza
Quiero enfatizar que "significado" no implica un resultado computacional. Claramente, 1 + 2 y 2 + 1 son iguales a 3. Sin embargo, los términos son distintos e implican un cálculo diferente incluso si tiene el mismo resultado. El significado es diferente, así como dos algoritmos de clasificación son diferentes.
Es posible que haya oído hablar del "árbol de sintaxis abstracta" (AST). La palabra "abstracto" aquí significa precisamente "ortogonal". ¡Técnicamente, la mayoría de los AST no son de hecho abstractos!
¿Quizás has oído hablar del lenguaje de programación "C"? La notación de tipo C no es abstracta. Considerar:
Así que aquí hay una declaración de función que devuelve el tipo
int
. El tipo de puntero a esta función viene dado por:Tenga en cuenta que no puede escribir el tipo de la función. ¡La notación de tipo C es una mierda! No es abstracto No es ortogonal. Ahora, supongamos que queremos hacer una función que acepte el tipo anterior en lugar de int:
Todo bien ... pero ... ¿y si queremos devolverlo?
Woops! Inválido. Vamos a agregar parens:
Woops! Eso tampoco funciona. Tenemos que hacer esto (¡es la única forma!):
Ahora está bien, pero tener que usar un typedef aquí es malo. C apesta. No es abstracto No es ortogonal. Así es como se hace esto en ML, que es:
Condenamos C en el nivel de sintaxis.
Ok, ahora vamos a flog C ++. Podemos arreglar la estupidez anterior con plantillas y obtener una notación similar a ML (más o menos):
pero el sistema de tipos real está fundamentalmente viciado por las referencias: si
T
es un tipo, ¿entonces esT&
un tipo? La respuesta es imprecisa: en el nivel de sintaxis, si tiene un tipo U = T &, entonces U & está permitido pero solo significa T &: una referencia a una referencia es la referencia original. Esto apesta! Rompe el requisito de unicidad semánticamente. Peor: T & & no está permitido sintácticamente: esto rompe el principio de sustitución. Por lo tanto, las referencias de C ++ rompen la ortogonalidad de dos maneras diferentes, dependiendo del tiempo de unión (análisis o análisis de tipo). Si quieres entender cómo hacer esto bien ... ¡no hay problema con los punteros!Casi ningún idioma real es ortogonal. Incluso Scheme, que pretende una gran claridad de expresión, no lo es. Sin embargo, se puede considerar que muchos buenos idiomas tienen una "base de características razonablemente similar a la ortogonal" y esa es una buena recomendación para un lenguaje, aplicado tanto a la sintaxis como a la semántica subyacente.
fuente
int (*intintfunc())(int) { ... }
: intintfunc es una función que no toma argumentos y devuelve un puntero a una función que toma 1 argumento int y devuelve un valor int.Probar la ortogonalidad es probar un negativo. Significa que no tienes construcciones que no sean ortogonales, lo que significa que es mucho más fácil demostrar que algo no es ortogonal de lo que es.
En la práctica, la mayoría de la gente habla sobre la ortogonalidad de los lenguajes de programación en términos de grados en lugar de ser completamente ortogonales o no. Cuando el conocimiento de hacer algo en un contexto se traduce en otro contexto y "hace lo que esperas", se dice que ese lenguaje es más ortogonal. LISP se considera altamente ortogonal porque todo es una lista, pero no creo que se pueda decir que es 100% ortogonal debido a algunas redundancias que lo hacen más fácil de usar. Se considera que C ++ no es muy ortogonal porque hay muchas pequeñas "trampas" en las que no funciona de la manera que piensas.
fuente
Advertencia, no sé nada sobre este tema.
Un rápido vistazo a Wikipedia parece indicar que la ortogonalidad se dirige principalmente a patrones de diseño y diseño de sistemas. En términos de lenguajes de programación, la entrada indica que los conjuntos de instrucciones son ortogonales si hay una y solo una instrucción para cada acción posible, o mejor dicho, ninguna instrucción se superpone a otra.
Para C #, me imagino que es ortogonal, ya que la mayoría de los trucos de sintaxis (
foreach
vienen a la mente) son simplemente front-end para versiones especialmente formadas de la construcción base (seforeach
convierten enfor
bucles). En general, el lenguaje solo es compatible con hacer cosas de una sola manera, a pesar de que el azúcar sintáctico proporciona formas adicionales de hacerlo. Y, por último, todo se compila enMSIL
(o como se llame en estos días) yMSIL
es probable que sea ortogonal.Si hace la advertencia de que el azúcar sintáctico es esencialmente un "envoltorio" para hacerlo de la "manera difícil", puede analizar las diversas características del lenguaje, omitir el azúcar y ver si hay construcciones que realmente se superponen. Si no, me imagino que podría declarar el idioma ortogonal.
Mis dos centavos.
fuente
do...while
se puede usar para proporcionar el mismo efecto quefor
? Nunca he oído hablar de ninguno de ellos como considerado azúcar sintáctico.do while
garantiza una ejecución de bucle único y verifica la condición después del hecho.for
comprueba primero la condición y no garantiza una sola ejecución.Continúas haciendo lo que estás haciendo, enumerando todas las combinaciones que funcionan o están prohibidas.
Eso es todo. Es bastante doloroso hacerlo.
Si todas las características se pueden dividir en subconjuntos disjuntos que no interfieren entre sí, entonces seguro, todo sería sensato.
Todas las estructuras de datos funcionan con todos los tipos primitivos. Todos los operadores de expresión trabajan con todos los tipos. Esas son definiciones comunes de ortogonalidad. Pero es posible que desee más (o menos)
A veces, sin embargo, hay casos especiales debido a sistemas operativos o bibliotecas heredadas que no son ortogonales.
Además, algunos tipos no son realmente muy conformes en absoluto. Por ejemplo, Python le permite comparar dos objetos de diccionario para "ordenar". Pero casi no hay una definición sensata de "ordenar" entre los diccionarios. Python define uno, pero es bastante discutible. ¿Ese caso especial hace que los diccionarios fallen una prueba de ortogonalidad?
¿Qué tan ortogonal es "suficientemente ortogonal"? ¿Qué es lo que necesita ver para ser feliz con el grado de ortogonalidad en su idioma.
fuente
La lista de características no ortogonales es de hecho larga en la mayoría de los lenguajes de programación, p. Ej.
Esos son algunos que me vienen a la mente, pero hay muchos otros, y también en otros idiomas.
Es difícil asegurarse de que no haya una interferencia sutil entre las características del lenguaje. Como CAR Hoare indica en su documento "Consejos sobre el diseño del lenguaje de programación":
Probablemente, un buen movimiento para aumentar la ortogonalidad es unificar conceptos (que va en la dirección de la respuesta @ karl-bielfeld). Si todo es, digamos una lista o un objeto, es probable que haya menos conflictos. O, en lugar de tener una clase anidada y un pensamiento posterior, conviértalo en una característica central.
La mayoría de los documentos sobre lenguajes de programación demuestran ciertas propiedades del lenguaje (p. Ej., Solidez de tipo) en un subconjunto (un "núcleo") del lenguaje que se formaliza. Aquí debemos hacer lo contrario, demostrar que todas las características se componen de forma segura. Además, eso significa que uno debe definir lo que significa "componer". ¿Significa "correr"? (En este caso, el enlace anterior sobre el caso de borde con escritura dinámica y estática es seguro). ¿Significa estar "seguro"? ¿Significa ser predecible desde el punto de vista del desarrollador?
Todo eso es muy interesante, pero también muy desafiante.
fuente