Cables

wire bard

En este post, me gustaría hablar sobre preguntas que son difíciles de responder, no porque solo los genios puedan hacerlo, sino porque a nuestro cerebro le pasan desapercibidas y además requieren un marco adecuado para poder dimensionarlas correctamente. Para comprenderlas mejor, necesitamos analizar el contexto en el que surgen. Algo similar ocurre en la programación: a menudo asumimos que estamos creando elementos nuevos al escribir un programa, cuando en realidad estamos utilizando piezas que ya existen dentro del lenguaje. Es decir, aunque parece que estamos inventando algo nuevo, en realidad solo estamos invocando y combinando elementos preexistentes. Te explico.

Los lenguajes de programación modernos nos ofrecen un conjunto de elementos predefinidos, como caracteres, constantes, números, operadores y palabras clave. Pon mucha atención a estos, ya que no hay más. Estos elementos no los inventamos cada vez que escribimos código, es decir, cuando los usamos en realidad no estamos haciendo magia (por mucho que nos haga sentir bien escribir uno que otro); simplemente los invocamos, utilizando una estructura definida por el lenguaje. Su existencia está determinada por el compilador o el intérprete, que asigna a cada elemento un significado y comportamiento específicos.

Apuesto a que siempre miras tu código y no le das mucha importancia a todos esos datos primitivos. El cerebro no les presta atención porque está trabajando en una capa de abstracción superior al funcionamiento de estos. Parece algo sin importancia, pero en realidad es muy útil si queremos entender cómo funciona el lenguaje en sí, no necesariamente nuestro programa, ya que este opera sobre esa capa de abstracción, a un nivel superior.


En programación, los elementos preexistentes son aquellos que ya están disponibles en el lenguaje y que usamos como bloques de construcción para desarrollar nuestras aplicaciones. Algunos ejemplos comunes incluyen:

  • Constantes de carácter: 'a', 'b', 'c', etc.
  • Números en distintas bases: 10, 0xA, 0b1010, etc.
  • Operadores: +, -, *, /, %.
  • Caracteres especiales: !, $, &, *, @.

Estos elementos no los creamos en tiempo de ejecución; simplemente invocamos su representación preexistente. Su existencia, aunque a veces parezca obvia, es crucial para que el lenguaje de programación funcione. Por ejemplo, una constante de carácter como 'a' ya está definida en el sistema, y un número como 10 tiene una representación binaria en el procesador.

Cuando utilizamos estos elementos, es importante recordar que no forman parte de la lógica específica de nuestro programa; más bien, son herramientas primitivas diseñadas para ser utilizadas como base. Su implementación es el resultado de decisiones previas tomadas en la construcción del lenguaje y el compilador.


El compilador o intérprete es donde reside la “existencia” de estos elementos. Su tarea es interpretar lo que escribimos en código fuente y traducirlo a un lenguaje que la máquina pueda entender. Por ejemplo:

  • Cuando usamos la constante 'a', el compilador la traduce a un valor numérico según la codificación de caracteres utilizada (como ASCII o Unicode).
  • Un número como 10 se representa en el sistema binario del procesador.

Esta traducción no ocurre mágicamente; el lenguaje de programación define reglas que el compilador sigue para identificar y procesar cada elemento. Estas reglas son lo que conocemos como tokens.

Imagínate el conjunto de elementos que están preexistentes para ser usados. Solo tienes que invocarlos, y el compilador se encarga de tratarlos o comportarlos según su uso. Por ejemplo, puedes usar los mismos caracteres y números para declarar un identificador (como una variable) que se diferencia de una constante literal solo porque no lleva comillas.

Solo una intromisión…

Me gustaría mencionar algo muy importante, y es que, sobre estos caracteres, constantes numéricas y símbolos se abstrae un concepto de orden superior, el cual es el significado de valor. Un valor es un conjunto de signos que pertenece a un grupo de categorías a nivel de datos. Suena bastante complejo, pero en realidad no lo es. Cuando almacenamos un dato en memoria para ser utilizado, digo asignamos porque me refiero al hecho de declarar un nombre (variable) a través de un identificador y referenciar datos mediante ese nombre. El compilador tiene que saber cómo acceder a esos datos sin perder precisión y significado. Así que los clasifica por longitud de lectura; a esta longitud del segmento de memoria le denomina tipo. Internamente, todos los valores tienen un tipo inherente, y esto es para poder acceder o escribir datos de manera convencional y gestionar bien la memoria existente.

Los compiladores manejan estos tipos eficientemente, reduciendo su cantidad de tipos primitivos necesarios. Se apoyan en una cantidad limitada de tipos primitivos como base (enteros, flotantes, caracteres, etc.) que pueden ser manipulados directamente por el hardware. Menos tipos significan menos reglas para gestionar cómo se almacenan y manipulan los datos, haciendo que el compilador pueda optimizar las operaciones de manera más predecible.

Aunque los lenguajes de programación de alto nivel ofrecen una variedad rica de tipos de datos (como arreglos, cadenas, e incluso objetos), estos suelen descomponerse en tipos primitivos durante la traducción al código máquina. Por ejemplo, una cadena se traduce en una secuencia de caracteres (char), a menudo terminada con un carácter nulo (\0).

Abordaremos con precisión el concepto de tipo en un artículo posterior. Por ahora, el concepto clave, además de las constantes numéricas y de carácter, es el de valor. Todos los valores están construidos a partir de estas constantes. Para entenderlo mejor, recordemos los tipos primitivos, como los enteros, los flotantes y los caracteres, que son representados mediante estos símbolos.


Tokens: Los Bloques Fundamentales

En el contexto de un lenguaje de programación, un token es la unidad más pequeña que tiene significado. Los compiladores dividen el código fuente en estos bloques para entenderlo mejor. Algunos tipos de tokens incluyen:

  • Palabras clave: if, while, return, function.
  • Identificadores: nombres de variables y funciones, como total o calculateSum.
  • Constantes: valores literales como 42, 'a' o true.
  • Operadores: +, ==, &&.
  • Separadores: ,, ;, {, }.

Por ejemplo, al declarar una variable como let x = 10;, el compilador divide esta línea en tokens:

  1. let (palabra clave)
  2. x (identificador)
  3. = (operador)
  4. 10 (constante)
  5. ; (separador)

Cada uno de estos tokens tiene un propósito y un comportamiento predefinido en el lenguaje.


Así que…

Cuando programamos, no estamos creando elementos completamente nuevos; estamos trabajando con un conjunto finito de herramientas preexistentes. Estas herramientas han sido cuidadosamente diseñadas para abstraer la complejidad del hardware y facilitar el desarrollo. Comprender estos fundamentos nos ayuda a apreciar mejor la estructura de los lenguajes de programación y su capacidad para transformar ideas en instrucciones ejecutables.

En resumen, programar es un ejercicio de combinar estos bloques preexistentes para construir algo único, pero siempre dentro del marco de lo que el lenguaje y el compilador permiten. ¡Y eso es lo que hace que programar sea tan fascinante!

Únete a la newsletter de BitSpace

Una actualización por semana. Todos los últimos artículos directamente en tu inbox.