c# - sibuc - ¿Los idiomas realmente dependen de las bibliotecas?
puc biblioteca catalogo (4)
Siempre me he preguntado cómo se gestionan las dependencias desde un lenguaje de programación hasta sus bibliotecas. Tome por ejemplo C #. Cuando comencé a aprender sobre computación, supondría (por error) que el lenguaje en sí está diseñado independientemente de las bibliotecas de clase que eventualmente estarían disponibles para él. Es decir, el conjunto de palabras clave del lenguaje (como for
ejemplo, class
o throw
) más la sintaxis y la semántica se definen primero, y las bibliotecas que se pueden usar desde el idioma se desarrollan por separado. Las clases específicas en esas bibliotecas, solía pensar, no deberían tener ningún impacto en el diseño del lenguaje.
Pero eso no funciona, o no todo el tiempo. Considera throw
. El compilador C # se asegura de que la expresión siguiente throw
resuelva a un tipo de excepción. Exception
es una clase en una biblioteca, y como tal, no debería ser especial. Sería una clase como cualquier otra, excepto que el compilador de C # le asigna esa semántica especial. Eso es muy bueno, pero mi conclusión es que el diseño del lenguaje depende de la existencia y el comportamiento de elementos específicos en las bibliotecas de clase.
Además, me pregunto cómo se gestiona esta dependencia. Si tuviera que diseñar un nuevo lenguaje de programación, ¿qué técnicas usaría para mapear la semántica de throw
a la clase muy particular que es Exception
?
Entonces mis preguntas son dos:
- ¿Estoy en lo correcto al pensar que el diseño del lenguaje está estrechamente relacionado con el de sus bibliotecas de clase base?
- ¿Cómo se gestionan estas dependencias desde el compilador y el tiempo de ejecución? ¿Qué técnicas se usan?
Gracias.
EDITAR. Gracias a aquellos que señalaron que mi segunda pregunta es muy vaga. Estoy de acuerdo. Lo que intento saber es qué tipo de referencias almacena el compilador sobre los tipos que necesita. Por ejemplo, ¿encuentra los tipos por algún tipo de identificación única? ¿Qué sucede cuando se lanza una nueva versión del compilador o las bibliotecas de clase? Soy consciente de que esto todavía es bastante vago, y no espero una respuesta precisa de un solo párrafo; más bien, son bienvenidos los consejos sobre literatura o blogs.
Asumiría (quizás erróneamente) que el lenguaje en sí está diseñado independientemente de las bibliotecas de clase que eventualmente estarían disponibles para él.
Su suposición es, en el caso de C #, completamente incorrecta. C # 1.0, CLR 1.0 y .NET Framework 1.0 fueron diseñados juntos. A medida que evolucionó el lenguaje, el tiempo de ejecución y el marco, los diseñadores de cada uno trabajaron muy estrechamente para garantizar que se asignaran los recursos correctos para que cada uno pudiera enviar nuevas características a tiempo.
No entiendo de dónde viene tu suposición completamente falsa; eso suena como una forma muy ineficiente de escribir un lenguaje de alto nivel y una gran manera de perder tus fechas límite.
Puedo ver escribir un lenguaje como C, que es básicamente una sintaxis más agradable para el ensamblador, sin una biblioteca. Pero ¿cómo podrías escribir, decir, async-await
sin tener al tipo que diseña Task<T>
en la sala contigo? Parece un ejercicio de frustración.
¿Estoy en lo correcto al pensar que el diseño del lenguaje está estrechamente relacionado con el de sus bibliotecas de clase base?
En el caso de C #, sí, absolutamente. Hay docenas de tipos que el lenguaje C # supone que están disponibles y documentados para funcionar correctamente.
Una vez pasé una hora muy frustrante con un desarrollador que estaba teniendo un problema completamente loco con un bucle foreach antes de descubrir que había escrito su propio IEnumerable<T>
que tenía métodos ligeramente diferentes que el IEnumerable<T>
real IEnumerable<T>
. La solución a su problema: no hagas eso.
¿Cómo se gestionan estas dependencias desde el compilador y el tiempo de ejecución?
No sé cómo comenzar a responder a esta pregunta increíblemente vaga.
Lo que intento saber es qué tipo de referencias almacena el compilador sobre los tipos que necesita. Por ejemplo, ¿encuentra los tipos por algún tipo de identificación única?
Obviamente, el compilador C # mantiene una base de datos interna de todos los tipos disponibles tanto en código fuente como en metadatos; esta es la razón por la que un compilador se denomina "compilador": compila una colección de datos sobre las fuentes y las bibliotecas.
Cuando el compilador de C # necesita, por ejemplo, verificar si una expresión que se emite deriva de o es idéntica a System.Exception, pretende hacer una búsqueda de espacio de nombres global en el System
, y luego realiza una búsqueda en Exception
, encuentra la clase y luego compara la información de clase resultante con el tipo que se dedujo para la expresión.
El equipo del compilador usa esta técnica porque de esa manera funciona independientemente de si estamos compilando su código fuente y System.Exception
está en metadatos, o si estamos compilando mscorlib y System.Exception
está en el código fuente.
Por supuesto, como una optimización del rendimiento, el compilador en realidad tiene una lista de "tipos conocidos" y completa esa lista antes de tiempo para que no tenga que gastar el gasto de hacer la búsqueda cada vez. Como se puede imaginar, la cantidad de veces que debe buscar los tipos incorporados es extremadamente grande . Una vez que se completa la lista, la información de tipo para System.Exception
se puede leer de la lista sin tener que hacer la búsqueda.
¿Qué sucede cuando se lanza una nueva versión del compilador o las bibliotecas de clase?
Lo que sucede es que un grupo completo de desarrolladores, probadores, gerentes, diseñadores, escritores y educadores se reúnen y pasan unos pocos millones de horas-hombre asegurándose de que el compilador y las bibliotecas de clases funcionen antes de su lanzamiento.
Esta pregunta es, nuevamente, imposiblemente vaga. ¿Qué tiene que pasar para hacer una nueva versión del compilador? Mucho trabajo , eso es lo que tiene que pasar.
Soy consciente de que esto todavía es bastante vago, y no espero una respuesta precisa de un solo párrafo; más bien, son bienvenidos los consejos sobre literatura o blogs.
Escribo un blog sobre, entre otras cosas, el diseño del lenguaje C # y su compilador. Está en http://ericlippert.com .
Todos los lenguajes de programación (prácticos) tienen un número mínimo de funciones requeridas. Para los idiomas modernos de "OO", esto también incluye un número mínimo de tipos requeridos.
Si se requiere el tipo en la Especificación del idioma , entonces se requiere, independientemente de cómo esté empaquetado.
Por el contrario, no se requiere que todo el BCL tenga una implementación de C # válida. Esto se debe a que no todos los tipos de BCL son requeridos por la especificación de idioma. Por ejemplo, System.Exception
(ver # 16.2) y NullReferenceException
son necesarios, pero FileNotFoundException
no es necesario para implementar el lenguaje C #.
Tenga en cuenta que, aunque la especificación proporciona definiciones mínimas para los tipos base (por ejemplo, System.String
), no define los métodos comúnmente aceptados (por ejemplo, String.Replace
). Es decir, casi todo el BCL está fuera del alcance de la Especificación del lenguaje 1 .
.. pero mi conclusión es que el diseño del lenguaje depende de la existencia y el comportamiento de elementos específicos en las bibliotecas de clase.
Estoy completamente de acuerdo y he incluido ejemplos (y límites de tales definiciones) arriba.
.. Si tuviera que diseñar un nuevo lenguaje de programación, ¿qué técnicas usaría para mapear la semántica de "lanzar" a la clase muy particular que es "Excepción"?
No miraría principalmente la especificación de C #, sino que miraría la especificación de Common Language Infrastructure . Este nuevo lenguaje debe, por razones prácticas, estar diseñado para interoperar con los lenguajes CLI / CLR existentes, pero no necesariamente debe ser "C #".
1 La CLI (y las referencias asociadas) definen los requisitos de un BCL mínimo. Por lo tanto, si se considera que una implementación válida de C # debe cumplir (o puede suponer) la CLI, existen otros muchos tipos que no se mencionan en la especificación C #.
Lamentablemente, no tengo suficiente conocimiento de la segunda (y más interesante) pregunta.
mi impresión es que
en idiomas como C # y Ada
el código fuente de la aplicación es portátil
el código fuente de la biblioteca estándar no es portátil
a través de compiladores / implementaciones