Cursos de lenguaje de programación (Bootstrap Part 1)

Esto es parte de una serie más grande conocida como “Cómo Programar Cualquier Cosa: Core Rulebook

Prefacio

Este artículo viene en los talones de dos otros postes que hice mucho más temprano sobre lenguajes de programación y memoria de la computadora. La razón por la que todavía no he escrito un tutorial de “Introducción a la programación” (como la lingüística, la filosofía y la electricidad) es doble. Uno, es el tema en el que soy el más experto y eso lleva a dos, hay mucha información y antecedentes que van a la programación de un dispositivo. Hay antecedentes matemáticos, hay conceptos abstractos de fondo, hay cómo los dispositivos computacionales dang funcionan y qué entorno está programando en el fondo. Quiero decir, los tutoriales que di en binario son sólo una punta del iceberg cuando se trata de cómo se podría programar una computadora. He pensado durante largos periodos de dónde diablos empiezo una serie sobre cómo programar? ¿Empiezo con la historia de contar? Porque para mí la programación es simplemente una extensión de la matemática puesta en uso de una manera aplicada y por lo tanto las abstracciones de contar y números son fundamentales para su éxito. ¿Empiezo con los fundamentos filosóficos del proceso de abstracción? Debido a que ser capaz de abstraer de los concretos hasta, y luego ser capaz de concretar a partir de los resúmenes hacia abajo también es fundamental para la programación exitosa. ¿Empiezo con los sistemas de reescritura de cadenas y las gramáticas de dichos lenguajes, tales como Extended Backus-Naur Form, explorando varios autómatas y lenguajes formales? Ese es un buen lugar para comenzar, pero es espeso en teoría.

He decidido lo que tengo que hacer es proporcionar lo que llamamos un “bootstrap” post sobre la programación. Estoy interesado en explorar un lenguaje en particular en una serie, en este caso el lenguaje de programación C, y necesito comenzar desde algún punto al que pueda remitir sin elucidar la historia de todo pensamiento abstracto. Estoy construyendo sobre un par de series que hice hace muchos años que comenzaron con lo que era una computadora, cómo funcionaba una computadora en general, cómo contar en binario y lo más importante para este artículo cómo funciona la memoria de una computadora y cuáles son lenguajes de programación. Estos posts son importantes para este post porque vamos a tocar en cada uno brevemente, por lo que también podría mirar en ellos. Son muy cortos y de mi viejo blog, por lo que no debe ser demasiado difícil.

El propósito de este artículo es introducir algunos “fundamentos” básicos o al menos características que la mayoría de los lenguajes de programación en uso hoy en día tienen o emplean. Al mismo tiempo introduce algunos conceptos básicos que se requieren para entender la mayoría de la programación que se aplica generalmente. Este artículo no cubre los diferentes paradigmas de programación, ni sus similitudes y diferencias, que se deja para otro post. Este artículo tampoco cubre los entornos / modos de programación especializados como la programación lógica en lenguajes como Prolog. En su lugar, este artículo se centra en conseguir que hasta la velocidad con los conceptos de programación general y penetrante que están ahí fuera en la naturaleza de hoy.

NOTA: Lo que voy a cubrir en este artículo se conoce como “programación imperativa”. Este es un modelo específico de programación, o un paradigma de programación. Hay muchos otros modelos, pero la programación imperativa es probablemente la más popular y la más aplicable en estos días. La mayoría de los lenguajes de programación de propósito general incluyen métodos de utilizar el paradigma imperativo.

¿Qué es la programación?

En nuestros tiempos modernos actuales estamos rodeados de máquinas milagrosas que pueden “pensar”. Es decir, pueden procesar la información de tal manera que puedan tomar diferentes acciones dependiendo de los datos que se les dan. No estamos en el punto, sin embargo, que una computadora puede simular el proceso de pensamiento de un cerebro humano exactamente, pero nos estamos acercando cada día. La clave para obtener estos dispositivos computacionales, sistemas de alarma de casa, redes de ordenadores, robots, teléfonos celulares, instalaciones de escritorio, para hacer lo que queremos que hagan es a través de la programación. La programación es el proceso de tomar una tarea o función abstracta, dividiéndola en pasos individuales (un proceso) y luego diciendo (instruyendo) uno de estos dispositivos de pensamiento para hacer esos pasos específicos exactos. Hacemos esto con lenguajes “formales” que son altamente específicos y precisos e ilustran cada pequeño paso que el dispositivo computacional debe tomar. Las computadoras no pueden, por ahora, llenar espacios en blanco para nosotros, así que tenemos que ser muy específicos en decirles qué hacer.

Estos lenguajes formales son artificiales, son hechos por el hombre y siguen reglas específicas. Estos son llamados lenguajes de programación. La forma en que le decimos a una computadora que haga algo depende del lenguaje de programación que escojamos. El post anterior (arriba) sobre los lenguajes de programación ilustra esto un poco más en profundidad. Por ahora, un lenguaje de programación es una forma de decirle a un ordenador qué hacer en algún nivel.

De una manera interesante, y cómo tienden a antropomorfizar el proceso, la programación es un poco como la magia. La magia es la aplicación de la voluntad a la realidad, “doblar” la realidad o influir en la realidad a través del proceso de pura voluntad si perdonas mi tangente. La programación es la aplicación de su voluntad a la computadora, forzándola para hacer lo que usted desea. Cuando puedas hacer que tu robot o programa comience a hacer lo que quieres en la naturaleza, es una perspectiva terriblemente emocionante … y casi mágico.

Elección De Idiomas

Hay cientos de lenguajes de programación para elegir para realizar cualquier tarea. La forma en que elija un lenguaje de programación en un momento dado depende de muchos factores, incluyendo qué bibliotecas están disponibles para él y qué puede hacer con él. A medida que se familiarice con la programación, comenzará a hacer preguntas más abstractas, como por ejemplo, qué tan fácil es hacer lo que quiero hacer en un idioma determinado. Ningún lenguaje de programación, incluso si es un lenguaje de programación general, es adecuado para cada tarea, aunque eso no impide que alguien haga un esfuerzo hercúleo para hacer que haga lo que quiere.

Hay muchas cualidades que un lenguaje de programación puede tener o ser medido por. ¿Es Turing completo? ¿Puede procesar o resolver este problema, o ese problema? Cuántas líneas de código se necesitan para hacer algo, y así sucesivamente. A medida que adquiera experiencia en varios idiomas, comenzará a ser capaz de apreciar preguntas como éstas y tomarlas en consideración al elegir el idioma en particular que desea emplear para resolver su problema.

Algunos de los lenguajes de programación más populares en estos días incluyen Java, Python, JavaScript, Go, R, PHP, C y C ++. Hay miríadas de otros lenguajes de programación para diversos propósitos, así como C #, Scratch, Haskell, PERL, Prolog, Verilog, BASIC, y así sucesivamente. La lista es realmente interminable. La clave aquí, sin embargo, es que muchos de estos lenguajes comparten constructos similares que los componen. Voy a cubrir algunas de estas similitudes aquí en este artículo.

Flujo del Programa

Es fácil olvidar a veces que la programación es generalmente, cuando se trata de las verdaderas tuercas y tornillos de un solo procesador (o núcleo), lineal. Ahora, hilos, sockets, multi-core, orientado a objetos y la programación simultánea le dirá lo contrario, pero en general, cuando llegue a un procesador (-core) sólo puede hacer una instrucción a la vez. Claro, el sistema operativo puede hacer malabares con los procesos, y varios procesadores pueden estar ejecutando múltiples instrucciones a la vez, pero en general es una instrucción a la vez.

Esto es cierto para cualquier tipo de programación que va a hacer. El programa más simple va de principio a fin, ejecutando una instrucción a la vez. Incluso si usted está programando en un paradigma orientado a objetos (llegaremos a eso) siempre está programando con la idea de que donde quiera que esté en el programa, ese es el único hilo de ejecución que la computadora va a hacer en ese particular hora. Rara vez es necesario preocuparse de que una declaración o expresión va a venir después de otro. Aunque usted puede construir sistemas no lineales, y lo hará, al programar los pasos que una computadora toma, está haciendo las cosas un paso a la vez en cualquier contexto dado.

Construcciones compartidas de muchos lenguajes de programación

En el mundo de la programación de hoy ha habido mucho trabajo en “estandarizar” una gran cantidad de cómo interactuamos con la computadora. Ahora, no hay un lenguaje estandarizado que todos usen, pero eso es algo bueno. Ni siquiera se puede “normalizar” el lenguaje de máquina porque cada procesador y el entorno en el que se ejecuta el procesador es diferente. Sin embargo, muchos lenguajes de programación modernos, más allá del montaje directo, tienen algunas características que comparten (aunque pueden implementarlas a su manera). Estos incluyen variables y tipos de datos, operadores, expresiones y sentencias, construcciones de control de flujo, funciones y subrutinas y dependiendo de la sofisticación del lenguaje orientada a objetos (la programación orientada a objetos estará en Bootstrap Parte 2). Expongo más adelante lo que están abajo:

Variables y tipos de datos

Cuando programamos a menudo necesitamos “almacenar” un número o fragmento de datos “en algún lugar” por un tiempo antes de que lo volvamos a procesar. Esto podría ser compararlo con otra pieza de datos, incrementarla, y así sucesivamente. El ordenador “almacena” datos, ya sean números o caracteres, en su memoria. Hay muchos tipos de memoria que se encuentran a lo largo del dispositivo computacional desde los registros del procesador, a la memoria de acceso aleatorio (RAM) para el almacenamiento a corto plazo, a los discos duros para el almacenamiento a largo plazo. La clave aquí es que cualquier lugar en la memoria es localizable mediante el uso de una dirección. Al “dar” a la computadora esta dirección, que suele ser un código numérico, podemos recuperar esa pieza de datos.

Ahora, retrocede un paso desde allí. Tenemos un mar de memoria, y cada punto en esa memoria está representado por un número. Eso es genial, pero mientras estamos programando a lo largo de si tuviéramos que recordar la dirección numérica de cada pequeña pieza de datos que alguna vez almacenamos en cualquier lugar, se convertiría en algo insoportable. Ahí es donde entran las variables con los lenguajes de programación actuales. Una variable es un identificador que “encapsula” la dirección de memoria detrás de una etiqueta fácil de recordar. Cuando queremos usar esos datos, o asignar nueva información a esos datos en esa dirección, solo usamos la variable. Piensa así: myVariable = 10  y myVariable> 20 .

En muchos lenguajes de programación la historia de la variable no termina allí, es sólo el comienzo. En lenguajes como C o Java, se debe escribir una variable, es decir, el programador tiene que definir qué tipo de datos se va a almacenar en la dirección de memoria de esa variable. Esto se conoce como tipo de datos. Los dos tipos de datos más simples son el número, que es un número entero, decimal flotante o número complejo, y una cadena, que es una lista de caracteres enlazados "como este" . Por ejemplo, el lenguaje C tiene el tipo char  para números de ocho bits, int  para dieciséis números de bit, etc.

Un tipo de datos importante que es ligeramente más complejo es el array. Una matriz es simplemente una lista de puntos de datos. De hecho, la cadena “como este” es realmente una matriz de caracteres como: 'c', 'o', 'm', 'o', ' ', 'e', 's', 't', 'e', 0 . Si esta lista se asignó a la variable “arr”, podría acceder a las partes individuales a través de un índice (normalmente a partir de 0): arr[0] (sería 'l'); arr[2] (sería 'k');  . Esto se llama indexar una matriz. La idea es que los datos dados sean una serie que sea indexable, como la memoria, con un número.

A veces se puede acceder a las matrices con cadenas u otros identificadores en algunos idiomas, generalmente “superiores”, como arr["clave"] . Estos tipos de matrices se conocen a menudo como matrices asociativas o diccionarios. Trabajan igual que los arrays numéricamente indexados, y simplemente devuelven cualquier valor asociado con la clave dada.

Los tipos de datos más complejos se pueden construir de esos dos tipos de tipos de datos en lo que llamaremos estructuras. Una estructura combinará múltiples tipos de datos y tipos de datos en un registro que puede actuar como un tipo de datos. Por ejemplo, un registro puede contener la edad, el nombre y la fecha de nacimiento de una persona. Esta estructura se puede llamar “persona”, y las variables que contienen esa combinación de tipos de datos son del tipo de datos “persona”. Esto se vuelve importante tarde en la programación orientada a objetos.

Los lenguajes que obligan a todas sus variables a ser un tipo de datos específico en un punto u otro, y en particular a nunca cambiar tipos, se llaman lenguajes de tipo estático. Hay lenguajes, especialmente lenguajes de scripting como PHP y Python, que permiten asignar cualquier tipo de datos a cualquier variable en cualquier momento. Esto suena como que añadiría a la confusión, pero en realidad, hay algunos beneficios serios de ella, como pato-mecanografía (más en el pato de mecanografía en la sección orientada a objetos.) Los idiomas que juegan rápido y suelto con los tipos de datos en Relación con las variables se denominan lenguajes de tipo dinámico.

Algunos programas también tienen una funcionalidad especial llamada constantes (como PHP). Las constantes son básicamente variables que nunca cambiarán el valor. Las asigna o define, una vez y luego las utiliza en el resto del programa. Normalmente las constantes se indican en el programa usando todas las letras mayúsculas. (COMO ESTE) Son útiles para configurar cualquier tipo de configuraciones que se utilizan se multiplican a lo largo del programa.

Entonces, ¿qué hacemos con todas estas variables? ¿Cómo decimos a la computadora que actúe sobre todos estos datos? La respuesta está en los operadores.

Operadores

 

Los lenguajes de programación están formados por operadores que hacen varias cosas. Por ejemplo, tiene el operador de asignación (normalmente “=”) que asigna el resultado de una expresión a una variable. También tiene el operador de suma (normalmente “+”) que agrega el resultado de dos expresiones para obtener otro resultado. No se preocupe si el uso de la expresión aquí es un poco confuso, vamos a cubrir las expresiones en breve.

Algunos operadores son unarios, lo que significa que operan en un operando como “++”: myVariable++ . Esto indica al lenguaje de programación que incremente el valor mantenido por myVariable en uno. Otros operadores son binarios, lo que significa que operan en dos operandos. Los operadores generalmente aritméticos son de este tipo, tales como suma, resta, división y multiplicación: 2 * 2; 3 / 1; 4 + 5; 9 - 3;  . Los operandos de este ejemplo están en el lado izquierdo y derecho del operador (aunque no todos los lenguajes de programación los ubican allí, como Lisp o PostScript). Hay el operador trinary inusual presente en algunos idiomas, que prueba generalmente una condición, pero la izquierda mejor hasta más adelante.

La idea general es que cuando se le da un operador, el lenguaje de programación calcula un valor y, dependiendo del operador, hace algo con ese valor.

Expresiones y declaraciones

En algunos idiomas la diferencia entre una expresión y una declaración es un poco borrosa. Por lo general, definir cualquier cosa que es inmediatamente calculable como una expresión, es decir, se puede sustituir por un valor tal como está. Una declaración es algo que hace algo, generalmente a través de la interpretación de un operador. Tanto las expresiones como las sentencias pueden utilizar operadores, y las expresiones y los enunciados pueden tener efectos secundarios. Un operador es un pedazo de código, generalmente un símbolo, que le dice a la computadora que haga algo o que calcule algo de cierta manera.

La manera más fácil de imaginar o entender a los operadores es pensar primero en las matemáticas. Si vemos lo siguiente: 2 + 3 + 5  pensamos a nosotros mismos, “Oh, eso es igual a 10, y eso es porque estamos agregando 2 a 5, y luego añadiendo ese resultado a otro 5.” Que mi amigo es una expresión usando el operador de adición. ¿Por qué es una expresión y no una declaración? Bueno, la expresión tal como se da en casi cualquier lenguaje de programación calculará a (se reemplazará con) el valor de 10, pero luego tan rápidamente como se calculó, se olvida porque no hicimos nada con él.

Donde como lo siguiente es una sentencia: myVariable = 10 . ¿Por qué es esto una afirmación? Utiliza el operador de asignación para hacer que myVariable (una variable, ver arriba) sea igual y almacenar el valor 10. Esto realmente hace algo por así decirlo, si yo fuera tipo myVariable  en el lenguaje de programación a partir de ahora será equivalente a 10.

Las expresiones y declaraciones son cosas difíciles. Por ejemplo, la resolución variable, que es lo que hemos realizado simplemente escribiendo myVariable  arriba es una expresión. Calculó el valor de myVariable y lo reemplazó. La línea myVariable = 2 + 5 + (3 * 6)  es una combinación de expresiones y una sentencia. Las expresiones pueden ser formadas por expresiones más pequeñas, siempre y cuando sean calculables, donde en este caso 2 + 5 + (3 * 6) se pueden dividir en expresiones mucho más pequeñas como:

Donde “exp” significa expresión, “stmt” significa declaración, y los guiones “-” representan operadores. La clave aquí es que cuando se da, una expresión se calcula y reemplaza, mientras que una sentencia se ejecuta (hace algo) y puede o no puede darnos un valor.

Control de flujo

Estás yendo y estás programando tu pequeño corazón, pero estás teniendo dificultades. Usted puede hacer que el robot por ejemplo, caminar diez pasos adelante y diez pasos a la derecha. Sin embargo, realmente le gustaría conseguir que sea capaz de caminar diez pasos adelante, y luego dependiendo de la entrada de un sensor de movimiento, caminar diez pasos a la izquierda o derecha. Ahora necesitamos algo llamado una construcción de control de flujo.

Condicional

The exact type of flow control statement we’re looking into here is called an “if-clause.”  There are several types of flow control statements including the “for loop”, a “while”, and such.  However, all of these statements/clauses rest on a particular type of expression (see above) that uses comparison operators (see above).  What do I mean by this?  Here are the general comparison operators most programming languages offer as the basic foundation:  <, >, >=, <=, == .  Respectively these mean “less than”, “greater than”, “greater than or equal to”, “less than or equal to”, and “equal to (or equivalence)”.  You use them like this:  variable1 > variable2; 6 <= variable3; myVariable == 6; .   This is a bit of a special expression in that it computes to a true or false value.  If the condition indicated is true, if variable1 is actually greater than variable2, the first expression is computed as “true”.  Many programming languages offer more sophistication with these truth-expressions (comparison expressions) such as a “not” operator, usually an exclamation point, the ability to enclose them in parentheses, and the ability to include more than one condition in a logical connection using “and” and “or” operators (usually && and ||).  For example in a more sophisticated language I might write:  (a < 3) && !((b == 4) || (b == 1)) .  This would read: “variable b is NOT 4 OR 1 AND variable a is less than 3.”  Don’t worry, the computer would compute all that out and give us a true or false result.

El tipo exacto de declaración de control de flujo que estamos viendo aquí se llama una “cláusula if”. Hay varios tipos de declaraciones de control de flujo, incluyendo el “for loop”, un “while”, y tal. Sin embargo, todas estas declaraciones / cláusulas se basan en un tipo particular de expresión (véase más arriba) que utiliza operadores de comparación (véase más arriba). ¿Qué quiero decir con esto? Éstos son los operadores de comparación general que ofrecen la mayoría de los lenguajes de programación como base básica: <,>,> =, <=, == . Respectivamente, significan “menos que”, “mayor que”, “mayor o igual a”, “menor o igual a”, y “igual a (o equivalencia)”. Los usas así: variable1> variable2; 6 <= variable3; MyVariable == 6;  . Esto es un poco de una expresión especial en que calcula a un valor verdadero o falso. Si la condición indicada es verdadera, si variable1 es realmente mayor que variable2, la primera expresión se calcula como “true”. Muchos lenguajes de programación ofrecen una mayor sofisticación con estas expresiones de verdad (expresiones de comparación) como un operador “no”, generalmente un signo de exclamación, la posibilidad de encerrarlos entre paréntesis y la capacidad de incluir más de una condición en una conexión lógica usando “Y” y “o” operadores (normalmente && y ||). Por ejemplo, en un lenguaje más sofisticado podría escribir: (a <3) &&! ((B == 4) || (b == 1)) . Esto sería: “la variable b NO es 4 O 1 Y la variable a es menor que 3.” No se preocupe, la computadora calcularía todo eso y nos daría un resultado verdadero o falso.

Estas expresiones de comparación son simplemente expresiones que devuelven un valor verdadero o falso, pero son todavía expresiones; El ordenador los calcula, reemplaza su valor y se mueve. ¿Cómo usamos decir, a <3? Una de las formas más sencillas de utilizar el resultado de la comparación es en una cláusula if. Una cláusula if es simplemente una manera de decirle a la computadora que ejecute un conjunto de sentencias si algo es verdadero y, opcionalmente, otro conjunto de sentencias si algo es falso en su lugar. Generalmente se estructura de esta manera (algunos lenguajes de programación no usan paréntesis):

Esto básicamente dice: “Si a es menor que 3 ejecuta statement1 y statement2, o bien (si a es mayor o igual a 3) ejecuta statement3 y statement4”.

Esto se llama una construcción de control de flujo porque interrumpe la interpretación paso a paso lineal del programa por la computadora, nos presenta una prueba y luego procede a diferentes estados dependiendo de esa prueba. Afecta al flujo del programa. Después de ejecutar la instrucción de cláusula if, el flujo continúa por el programa como normal. Tenga en cuenta que la cláusula else es opcional la mayor parte del tiempo, pero puede utilizarse en caso de que desee algo si algo es falso sin escribir una nueva cláusula if.

Construcciones en bucle

¿Qué sucede cuando quieres algo un número de veces pero no quieres copiar y pegar las declaraciones una y otra vez en el programa? Puede usar una construcción de bucle. Hay varias construcciones de bucle que un lenguaje dado puede tener, pero normalmente tienen como base los dos siguientes: el bucle while y el bucle for. También hay el bucle foreach y el bucle do-while.

Una construcción de bucle utiliza una variable y una expresión de condición para determinar cuántas veces ejecutará sus sentencias de inclusión. Normalmente, la variable se incrementa, o se actualiza de otro modo, cada vez a través del bucle, y tan pronto como se cumple la condición en la expresión dada, el bucle se detiene. Es posible no actualizar la variable correctamente, o escribir una declaración de condición incorrecta y causar lo que se conoce como un bucle infinito. Estos, salvo en circunstancias muy específicas, deben ser evitados.

La sintaxis o construcción de un bucle while dado se parece a esto (algunos idiomas no usan paréntesis):

Como puede ver, es muy parecido a una cláusula if con el beneficio añadido de que el bucle volverá al principio de los paréntesis y comenzará todo de nuevo siempre y cuando la condición de la expresión se evalúe como verdadera. En este caso, si a comienza igualando 0, instrucción1 y instrucción2 se ejecutarán 3 veces. Uno para a = 0, uno para a = 1, y uno para a = 2.

Una vez más, la razón por la que esto se considera una construcción de control de flujo es porque toma el flujo lineal normal del programa (siguiente instrucción, siguiente instrucción, siguiente instrucción …) y lo hace “retroceder” y repetir ciertas instrucciones una y otra vez hasta Se cumple una condición.

La sintaxis o la construcción de un bucle for es un poco más complicada, y tomaré de la versión en lenguaje C para mostrar la sintaxis usual, pero muchos idiomas serán diferentes:

Aquí vemos un bucle for consiste en un cuerpo de sentencias (statement1-3), y en su cláusula condicional dos sentencias y una expresión condicional. Primero inicializamos la variable que se va a utilizar, a (a 0). A continuación, determinamos la condición que determinará si el bucle se ejecutará de nuevo (a <5). Por último, le decimos al ordenador qué hacer al final de cada bucle (después de ejecutar la instrucción3, que es incrementar uno por uno).

En este caso se ejecutarán instrucción1, instrucción2 y instrucción3, en ese orden cinco veces (una vez para a = 0, una vez para a = 1, otra vez para a = 2, a = 3 y a = 4).

La sintaxis o construcción de un bucle foreach es definitivamente dependiente del lenguaje. En este caso, voy a usar la versión PHP del bucle foreach para ilustrar su funcionalidad. Un bucle foreach difiere de un bucle for en el que itera (o pasos a través de uno a la vez) sobre un array (véase más arriba). Es decir, asigna un solo elemento de una matriz para una variable temporal que las sentencias dentro del bucle pueden usar. He aquí un ejemplo para ilustrar esto:

En este caso, la sentencia 1 y la instrucción 2 se ejecutarán seis veces, y en cada bucle $ val será igual al siguiente elemento en la matriz “arr”: val = 0, val = 5, val = 8, 2, 4, Los lenguajes de nivel superior como los lenguajes de scripting tienen este tipo de construcción de control de flujo por lo que es una buena idea familiarizarse con ella ahora. No todos los idiomas tienen este constructo, y los que lo hacen a menudo tienen una sintaxis muy variable (como usar “en” en lugar de “como”).

La última expresión / declaración de control de flujo que cubriremos es la función o subrutina.

Funciones y subrutinas

Así que tenemos un programa, y va de principio a fin, aunque a lo largo del camino dependiendo de los datos que puede ejecutar ciertas declaraciones y no otras, así como algunas partes se repiten un cierto número de veces, pero en general, obtenemos de Empezar a acabar. Todo está bien y bien, ¿verdad? Bueno, volvamos a nuestro pequeño robot.

Digamos que queremos que cada vez que nuestro robot debe mostrar una respuesta feliz, él levanta los brazos, sus ojos se vuelven verdes, y dice: “¡Yay!” Eso sería muy lindo ¿no? Sin embargo, nos presentan un poco de problema. Él podría darnos su respuesta feliz de tres pasos en muchas diversas épocas y en respuesta a muchas diversas clases de entrada. A partir de ahora, con nuestros conocimientos de programación, tenemos que insertar esos tres pasos específicos en todas partes del programa para que pueda hacer esa respuesta. Esa no es una buena idea.

Por una parte, ¿qué pasa si decides cambiar sus ojos a naranja? Bueno, siempre puedes hacer que el color de sus ojos sea constante (ver arriba) y usarlo y cambiar la constante a naranja. Bien, ¿qué pasa si decides después levantar solo un brazo en vez de ambos? Entonces tendrás que ir a través del programa entero y encontrar cada instancia donde él levanta ambos brazos para decir, “Yay” y lo reemplaza con una declaración levantando solamente un brazo. Eso es tedioso y propenso a errores. Entonces, ¿qué vamos a hacer?

La respuesta es una subrutina. No todos los idiomas tienen subrutinas básicas y en su lugar implementar todo esto como una función. Vamos a llegar a las funciones en un momento, ya que tienen alguna funcionalidad (no juego de palabras intencionado) que las subrutinas no. Una subrutina es una colección de declaraciones que la computadora puede “llamar” en cualquier momento dado, y luego “volver de” al flujo principal del programa. Es decir, el programa se detiene y registra dónde se encuentra en el programa, salta a las sentencias contenidas en la subrutina, las ejecuta y luego regresa a donde estaba antes.

Esto es astuto! Ahora podemos escribir la feliz respuesta de nuestro robot como una subrutina, y luego podemos “saltar” o llamar a esa subrutina desde cualquier parte del código y volver como acabábamos de escribir ese código allí mismo. Eso es práctico porque ahora si escribimos nuestro programa apropiadamente, sólo cambiamos la subrutina para levantar una mano y su “reflejada” en cualquier otra parte del programa. Podría parecer algo así (en BASIC):

Usted puede ver aquí el operador “gosub” salta el programa a “línea” 10000, y luego el operador “volver” salta el flujo del programa de nuevo a donde vino. ¡Muy agradable! Sin embargo, hay algunas deficiencias en las subrutinas. ¿Qué pasa si usted quiere pasar algo de información a la subrutina para que pueda funcionar un poco diferente? Es decir, darle algún aporte? ¿O qué si querías devolver un valor de la subrutina, porque la subrutina calculó algo? En este ejemplo BASIC (juego de palabras intencionado) tendrías que usar variables globales (para obtener más información sobre el ámbito global leída a continuación), y ésas pueden resultar desordenadas. Una mejor respuesta es una función.

Una función es básicamente una subrutina pero viene con algunas campanas y silbidos añadidos. La primera funcionalidad adicional que tiene es que puede tomar lo que se llaman argumentos. Estas son piezas de datos que se pueden “pasar” a la función cuando se le solicita. Se definen por variables en la definición de función que sólo se utilizan en esa función (véase el ámbito a continuación). Otra pieza del rompecabezas es que las funciones pueden devolver valores. En lugar de simplemente volver a donde estaba en el programa al regresar, el ordenador puede sustituir un valor calculado en la función como el valor de la función cuando se llama. Aquí hay un ejemplo:

Aquí definimos una función llamada suma que simplemente añade números juntos. Aquí suma es el nombre de la función, así que cuando usamos ese identificador en otra parte del programa, la computadora sabe que estamos “llamando” a una función. Puede ver dentro de la definición de función que identificamos “arg1” y “arg2”. Estos son los argumentos de la función, ya que contienen los datos que se “pasan” a la función cuando se llama desde otra parte del programa. Dentro del bloque de funciones de sentencias, vemos que define una variable “localvar” (más sobre esto en un momento), que almacena el resultado de la expresión arg1 + arg2. Por último, devuelve localvar, que devuelve cualquier dato que se almacena en localvar. Esto reemplaza la llamada de función original con el valor de retorno y ese valor se utiliza en el resto de la instrucción de llamada.

Me doy cuenta de que es una gran cantidad de magia que va en todos a la vez así que voy a romper.

Digamos que hemos definido la función “suma” como hemos hecho antes. Pasemos a través de cuando ejecutamos la primera sentencia sumvar1:

Espero que este diagrama pueda ilustrar el proceso que acabo de iterar. En resumen, se pasan valores a las funciones cuando se les llama. Estos valores se asignan como los argumentos de la función, la función entonces esperanzadamente actúa sobre estos argumentos y devuelve un valor.

Tenga en cuenta, porque las llamadas de función son reemplazables con valores de retorno que no son en realidad declaraciones, aunque algunos lenguajes de programación pueden ser diferentes, pero en su lugar son expresiones. Son inmediatamente computables. Esto se confunde porque a veces las funciones tienen efectos secundarios y hacer las cosas también, no sólo calcular las cosas. Pero en general en la mayoría de los idiomas, ya que pueden resolver a un valor de retorno son expresiones.

Truco aseado, sin embargo, ya que son expresiones, se pueden utilizar en otras construcciones de control de flujo, como la cláusula if y while. Esto se debe a que la función puede devolver un valor verdadero o falso, y eso es todo lo que la cláusula if o loop while están buscando al evaluar su expresión. Así que usted podría tener algo como esto:

En general, puede utilizar una llamada de función o invocación en cualquier lugar que pueda utilizar una expresión.

Alcance variable

Usted puede haber notado que cuando hicimos nuestra variable localvar en nuestra función de la suma la etiqueté “local”. Esto se debe a algo también presente en la mayoría de los lenguajes de programación populares. Ese es el concepto de alcance.

El alcance es un concepto algo abstracto, y cada lenguaje de programación desafortunadamente tiene sus propias definiciones del alcance. El alcance es básicamente la idea de donde se puede hacer referencia a lo que en el lenguaje. Lo que quiero decir es que si hago una variable aquí, ¿puedo referirme a esa variable aquí? Si hago una función aquí, ¿puedo referirme a esa función en esta otra parte del programa? La respuesta a eso es el alcance. La idea es que hay en general dos ámbitos diferentes. Existe el alcance global donde cualquier cosa definida en él puede ser referenciada en cualquier parte del programa, y hay más ámbitos más finos que son más estrechos y más estrechos de allí. Algunos lenguajes de programación tienen alcance de módulo, ámbito de archivo y así sucesivamente. Me refiero a todos ellos como ámbitos locales. Un ámbito local es un lugar en el programa donde si se define algo, como una función o una variable, otras partes del programa no van a poder “ver” o referenciarlo. Voy a dar un ejemplo:

Esto genera un error si estamos utilizando el ámbito de bloqueo. Hay muchos modelos diferentes de alcance, y el alcance adquiere una dimensión completamente nueva cuando llegamos a clases y objetos (post siguiente). Esto arroja un error porque definimos mylocalvarv en la función myFunc. Cada función define su propio ámbito local, y en este caso mylocalvar entra en el ámbito de esa función particular. Cualquier cosa fuera de esa función, el código principal, otra función, etc. no puede acceder a ese ámbito de funciones. De hecho mylocalvar es olvidado por la computadora tan pronto como la función regresa. Así que cuando intento asignar mylocalvar a myglobalvar, no puedo porque mylocalvar no existe. Ese es el poder del alcance.

Conclusión

Con variables, tipos de datos, control de flujo, funciones, expresiones, sentencias, subrutinas, etc., está preparado para comprender más completamente cualquier programación que surja de cualquiera de los lenguajes populares de uso general. Ése es realmente el núcleo de lo que compone la programación hoy (concedido que usted no está utilizando un lenguaje más especializado tal como Prolog o LISP). Usted puede conseguir bastante lejos con esta comprensión en C, PHP, Python, y más. Cada lenguaje de programación tiene variaciones en estos constructos y así tendrás que aprender cada uno si quieres programar en ese idioma, pero éstos son el núcleo.

En el siguiente post espero explorar la programación orientada a objetos y la cantidad de términos y matices que nos proporciona a los programadores. Aprenderás cosas como clases, objetos, prototipos, herencia, polimorfismo, oh mi! ¡Nos vemos la próxima vez!

Esto es parte de una serie más grande conocida como “Cómo Programar Cualquier Cosa: Core Rulebook

Si usted aprecia mis tutoriales y su sabiduría, por favor considere apoyarme en Patreon.

Sin embargo, si un compromiso mensual es un poco demasiado necesitado para usted, podría considerar comprarme una taza de café.

photo credit: catsocmedia Staying hydrated via photopin (license)

También te podría gustar...

Deja un comentario

A %d blogueros les gusta esto: