Principios de programación - Camilo Chacón Sartori - E-Book

Principios de programación E-Book

Camilo Chacón Sartori

0,0
29,99 €

-100%
Sammeln Sie Punkte in unserem Gutscheinprogramm und kaufen Sie E-Books und Hörbücher mit bis zu 100% Rabatt.
Mehr erfahren.
Beschreibung

¿Cuáles son los principios subyacentes a toda herramienta en programación? Si quiere conocer los ocho principios, técnicos y conductuales, que dan respuesta a esta pregunta, ha llegado al libro indicado. En una época donde cada día surgen nuevas tecnologías, el beneficio de conocer conceptos transversales a todas ellas no solo es imprescindible, sino también necesario. Además, con la llegada de sofisticadas aplicaciones de inteligencia artificial, la pregunta ya no reside en qué herramienta aprender, sino en qué tienen en común para poder integrarlas. Gracias a la lectura de este libro, descubrirá los cinco tomos que lo componen y que dan soporte a la nueva forma de entender la programación. "Tomo I: Aprenderá los fundamentos básicos de las matemáticas y de la programación. "Tomo II: Conocerá los principios de programación. "Tomo III: Dispondrá de una introducción histórica y práctica a los diversos sistemas de la computación, como los lenguajes de programación, los sistemas operativos, las bases de datos, los sistemas distribuidos y la inteligencia artificial. "Tomo IV: Analizará el diálogo que presenta los desafíos de la ingeniería de software. "Tomo V: Disfrutará de reflexiones y consejos para crecer como profesional. No pierda la oportunidad de iniciar el camino que le propone este libro, que va desde la historia de este campo del conocimiento hasta la programación en sí misma. Le suscitará nuevas ideas que impulsarán su carrera como programador. Camilo Chacón Sartori es doctorante en el Instituto de Investigación en Inteligencia Artificial (IIIA-CSIC) y en la Universidad Autónoma de Barcelona. Obtuvo su grado y máster en ingeniería en informática con distinción máxima. Ha publicado dos libros: Computación y programación funcional y Mentes geniales. La vida y obra de 12 grandes informáticos, ambos con la editorial Marcombo. Su principal proyecto, "Había una vez un algoritmo", es un pódcast y un newsletter donde reflexiona sobre temas técnicos, científicos y filosóficos concernientes a la informática.

Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:

EPUB
MOBI

Seitenzahl: 608

Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



Principios de programación

Camilo Chacón Sartori

Principios de programación

Camilo Chacón Sartori

 

 

Principios de programación

Primera edición, 2023

© 2023 Camilo Chacón Sartori

© 2023 MARCOMBO, S.L.

     www.marcombo.com

Diseño de la cubierta: ENEDENÚ DISEÑO GRÁFICO

Corrección: Haizea Beitia

Maquetación: Artemio Naiza

Directora de producción: M.a Rosa Castillo

Cualquier forma de reproducción, distribución, comunicación pública o transformación de esta obra solo puede ser realizada con la autorización de sus titulares, salvo excepción prevista por la ley. Diríjase a CEDRO (Centro Español de Derechos Reprográficos, www.cedro.org) si necesita fotocopiar o escanear algún fragmento de esta obra.

ISBN del libro en papel: 978-84-267-3682-6

ISBN del libro electrónico: 978-84-267-3737-3

Producción del ePub: booqlab

ÍNDICE DE CONTENIDOS

NOTA AL LECTOR

AGRADECIMIENTOS

INTRODUCCIÓN

MAPA DE LECTURA

TOMO I – FUNDAMENTOS

CAPÍTULO 1 LOS FUNDAMENTOS MATEMÁTICOS

1.1. INTRODUCCIÓN

1.2. LÓGICA

1.2.1. Lógica proposicional

1.3. CONJUNTOS

1.3.1. Notación

1.3.2. Subconjunto

1.4. CONCLUSIÓN

1.4.1. Lecturas sugeridas

CAPÍTULO 2 CONCEPTOS ELEMENTALES

2.1. INTRODUCCIÓN

2.2. SECUENCIALES

2.2.1. Variables

2.2.2. Condicional

2.2.3. Descomposición de conectivas

2.2.4. Bucle

2.3. FUNCIONALES

2.3.1. Función

2.3.2. Recursión

2.4. SECUENCIAL VS. RECURSIVIDAD

2.5. CONCLUSIÓN

CAPÍTULO 3 ALGORITMOS Y ESTRUCTURAS DE DATOS

3.1. INTRODUCCIÓN

3.2. ALGORITMOS COMO TECNOLOGÍA

3.2.1. Análisis de algoritmos

3.2.2. Clasificación

3.3. ESTRUCTURAS DE DATOS COMO COMPLEMENTO

3.3.1. Arreglos

3.3.2. Listas enlazadas

3.4. OTRAS

3.5. CONCLUSIÓN

CAPÍTULO 4 PENSAMIENTO COMPUTACIONAL

4.1. INTRODUCCIÓN

4.2. ORIGEN

4.3. LOS CINCO ASPECTOS BÁSICOS DEL PENSAMIENTO COMPUTACIONAL

4.3.1. Modularidad

4.3.2. Estructura de datos

4.3.3. Encapsulación

4.3.4. Estructuras de control

4.3.5. Recursión

4.4. OTROS GRUPOS DE CONCEPTOS DEL PENSAMIENTO COMPUTACIONAL

4.5. CONCLUSIÓN

4.5.1. Lecturas sugeridas

TOMO II – PRINCIPIOS

PRINCIPIOS TÉCNICOS

CAPÍTULO 1 DISEÑO

1.1. INTRODUCCIÓN

1.2. LOS PRERREQUISITOS DE UN DISEÑO

1.2.1. Objetivo del diseño de software

1.3. CONCEPTOS GENERALES

1.3.1. Descomposición y composición

1.3.2. Refactorización

1.3.3. Patrones de diseño

1.4. COMUNICACIÓN ENTRE PERSONAS

1.4.1. Diseño e implementación

1.4.2. Lenguajes de modelado

1.4.3. El futuro del diseño de software

1.5. CONCLUSIÓN

1.5.1. Lecturas sugeridas

CAPÍTULO 2 ESTADO

2.1. INTRODUCCIÓN

2.2. ASIGNACIÓN

2.2.1. Flujo de estados

2.2.2. Lenguaje ensamblador

2.3. ORDEN Y TIEMPO

2.3.1. Autómata finito (determinista y no-determinista)

2.3.2. Autómata celular

2.4. CONCLUSIÓN

2.4.1. Lecturas sugeridas

CAPÍTULO 3 RECURSO

3.1. INTRODUCCIÓN

3.2. COMPLEJIDAD ALGORÍTMICA

3.2.1. Lineal

3.2.2. Cuadrática

3.2.3. Exponencial

3.2.4. Logarítmica

3.3. LIMITACIONES

3.4. AVANCES DEL HARDWARE

3.5. MÉTRICAS

3.5.1. Particulares

3.5.2. Generales

3.6. CONCLUSIÓN

3.6.1. Lecturas sugeridas

CAPÍTULO 4 COORDINACIÓN

4.1. INTRODUCCIÓN

4.2. COMUNICACIÓN: ORDEN Y TIEMPO

4.2.1. Exclusión mutua

4.3. CONCURRENCIA Y PARALELISMO

4.3.1. Ley de Amdahl

4.3.2. ¿Cuándo paralelizar?

4.3.3. GPU

4.4. COMPUTACIÓN DISTRIBUIDA

4.4.1. MapReduce

4.4.2. Paso de mensajes

4.4.3. Llamada a procedimiento remoto

4.5. CONCLUSIÓN

4.5.1. Lecturas sugeridas

CAPÍTULO 5 TRANSFORMACIÓN

5.1. INTRODUCCIÓN

5.2. REPRESENTACIONES

5.2.1. Funciones

5.2.2. Formato de fichero

5.2.3. Sistema de numeración

5.2.4. Serialización

5.2.5. Computación reversible

5.3. OTROS TIPOS DE TRANSFORMACIONES

5.4. CONCLUSIÓN

5.4.1. Lecturas sugeridas

PRINCIPIOS CONDUCTUALES

CAPÍTULO 6 DOCUMENTACIÓN

6.1. INTRODUCCIÓN

6.2. ¿DOCUMENTA, POR FAVOR?

6.3. LOS PROBLEMAS DE DOCUMENTAR UN SOFTWARE

6.4. ESTRATEGIAS PARA DOCUMENTAR

6.4.1. El código como documentación

6.4.2. Documentación viva

6.5. CONCLUSIÓN

6.5.1. Lecturas sugeridas

CAPÍTULO 7 EVALUACIÓN

7.1. INTRODUCCIÓN

7.2. PRUEBAS DINÁMICAS

7.2.1. Funcionales

7.2.2. No funcionales

7.3. PRUEBAS ESTÁTICAS

7.3.1. Inspección de los requerimientos de software

7.3.2. Análisis estático

7.4. REPLICACIÓN Y CONTRASTACIÓN

7.4.1. ¿Cómo replicar?

7.4.2. ¿Cómo contrastar?

7.5. CONCLUSIÓN

7.5.1. Lecturas sugeridas

CAPÍTULO 8 ETHOS

8.1. INTRODUCCIÓN

8.2. LA RESPONSABILIDAD FRENTE A LA INTELIGENCIA ARTIFICIAL

8.2.1. IA y robótica

8.2.2. IA y sexualidad

8.2.3. Principio ético

8.3. ¿UN PROGRAMADOR TIENE RESPONSABILIDAD?

8.4. ¿QUÉ ES SER UN BUEN PROGRAMADOR?

8.4.1. Moralidad y programación

8.5. CONCLUSIÓN

8.5.1. Lecturas sugeridas

TOMO III – SISTEMAS

CAPÍTULO 1 LENGUAJES DE PROGRAMACIÓN

1.1. INTRODUCCIÓN

1.2. BREVE HISTORIA

1.3. COMPONENTES DE UN LENGUAJE DE PROGRAMACIÓN

1.3.1. Sintaxis

1.3.2. Semántica

1.4. CATEGORÍAS DE LENGUAJES

1.4.1. Generales

1.4.2. Dominio específico

1.5. ESTILOS DE LENGUAJES

1.5.1. Funcional

1.5.2. Imperativo

1.5.3. Orientado a objeto

1.5.4. Otros

1.6. DISEÑO E IMPLEMENTACIÓN

1.7. FUTURO

1.8. CONCLUSIÓN

1.8.1. Lecturas sugeridas

CAPÍTULO 2 SISTEMAS OPERATIVOS

2.1. INTRODUCCIÓN

2.2. BREVE HISTORIA

2.3. CONCEPTOS FUNDAMENTALES

2.3.1. Virtualización

2.3.2. Concurrencia

2.3.3. Persistencia

2.4. FUTURO

2.5. CONCLUSIÓN

2.5.1. Lecturas sugeridas

CAPÍTULO 3 BASE DE DATOS

3.1. INTRODUCCIÓN

3.2. BREVE HISTORIA

3.3. BASES DE DATOS RELACIONALES

3.3.1. Modelo relacional

3.4. BASES DE DATOS NO RELACIONALES (NOSQL)

3.4.1. Documentos

3.4.2. Clave-valor

3.4.3. Grafos

3.4.4. Vectores

3.5. FUTURO

3.6. CONCLUSIÓN

3.6.1. Lecturas sugeridas

CAPÍTULO 4 SISTEMAS DISTRIBUIDOS

4.1. INTRODUCCIÓN

4.2. BREVE HISTORIA

4.3. ARQUITECTURAS DE COMPUTACIÓN DISTRIBUIDA

4.3.1. Basada en capas

4.3.2. Orientada a servicios

4.3.3. Publicador-suscriptor

4.4. CARACTERÍSTICAS

4.4.1. Procesos

4.4.2. Comunicación

4.4.3. Coordinación

4.4.4. Consistencia y replicación

4.4.5. Tolerancia a fallas

4.4.6. Seguridad

4.5. FUTURO

4.6. CONCLUSIÓN

4.6.1. Lecturas sugeridas

CAPÍTULO 5 INTELIGENCIA ARTIFICIAL

5.1. INTRODUCCIÓN

5.2. UNA BREVE HISTORIA

5.3. ENFOQUE SIMBÓLICO

5.4. ENFOQUE PROBABILISTA

5.4.1. Aprendizaje automático (Machine Learning)

5.4.2. Aprendizaje profundo (Deep Learning)

5.5. FUTURO

5.6. CONCLUSIÓN

5.6.1. Lecturas sugeridas

TOMO IV – SOMOS HUMANOS

CAPÍTULO 1 BUENAS PRÁCTICAS

CAPÍTULO 2 INGENIERÍA DE SOFTWARE

CAPÍTULO 3 TIPOS DE SOFTWARE

TOMO V – BUENA VIDA

CAPÍTULO 1 APRENDIZAJE DE PROGRAMACIÓN

1.1. INTRODUCCIÓN

1.2. HERRAMIENTAS

1.2.1. El terminal es su mejor amigo

1.2.2. La importancia de depurar

1.2.3. Cuando el control de versiones es útil

1.2.4. Manipular texto

1.2.5. Reinventar la rueda

1.2.6. Use generadores de código

1.3. BUENAS PRÁCTICAS

1.3.1. Sobre leer código

1.3.2. Cree una historia de su código

1.3.3. Sobre escribir código

1.4. AVANZAR EN SU CARRERA

1.4.1. Averigüe qué tipo de programador es

1.4.2. Cuando enseñar también significa aprender

1.4.3. Construya una comunidad

1.5. FILOSÓFICOS

1.5.1. Pensar antes de programar

1.5.2. Cuide sus palabras

1.5.3. Sea analítico

1.5.4. Procure ser un generalista

1.6. CONCLUSIÓN

1.6.1. Lecturas sugeridas

CAPÍTULO 2 VIDA PERSONAL

2.1. INTRODUCCIÓN

2.2. CIENCIAS

2.2.1. La programación no son matemáticas, ¡pero estas ayudan!

2.2.2. Las ciencias como un faro en la oscuridad

2.3. ARTES Y HUMANIDADES

2.3.1. La música y la programación

2.3.2. Dibujo como inspiración

2.4. OCIO

2.4.1. Pasear, mirar y escuchar

2.4.2. No hacer nada

2.5. CONCLUSIÓN

2.5.1. Lecturas sugeridas

REFLEXIONES FINALES

ÍNDICE DE NOMBRES

ÍNDICE TEMÁTICO

 

 

Para Computación,que, con justa razón, me sigue rechazando,este será mi tercer —sutil y desquiciado— intento.

 

 

El tiempo que tenemos no es corto;pero perdiendo mucho de él, hacemos que lo sea,y la vida es suficientemente larga para ejecutar en ella cosas grandessi la empleamos bien.Séneca

NOTA AL LECTOR

Hace años, acaso por una cierta ingenuidad y entusiasmo propio de la juventud, quise escribir un libro que concentrara todo lo que sé de la programación, una forma de restituir la mano que me tendió cuando mi único camino era la informática. Desde entonces ha pasado un tiempo y ahora usted tiene en su poder esta promesa que hice: un libro que yo hubiera querido leer y que no encontré; un libro que intentara aunar gran parte de los conceptos presentes en la programación; un libro que, además de ser una apuesta, es un intento de romper la clásica estructura de un manual de programación, pues este es un libro generalista, no se enfoca en nada en particular, ni en un área ni en una herramienta, pero no pierde de vista que la parte práctica es la culminación de la programación.

Antes bien: es necesario recorrer un camino lleno de historias, de conceptos y de algoritmos, e igualmente, por qué no decirlo, de sueños y de pensar cómo podría ser la programación como campo de estudio, algo que, en la actualidad, no es.

Así pues, la obra que tiene en su poder fue pensada como el ingreso a una biblioteca pública dedicada a la informática, donde en algunas estanterías hallará libros de historia del campo, en otras encontrará libros de ficción sobre programación, caminando por el pasillo de al lado podrá hojear libros técnicos… Y así, mientras recorre esta biblioteca —y es la idea que tengo— le irán surgiendo nuevas ideas y lecturas. ¡Más que un fin es el inicio del camino!

¡Bienvenido/a a su casa!

Espero que disfrute de este libro de programación que, a su vez, reflexiona sobre ella.

 

Castro, Chile1

____________

1 Este libro fue escrito casi en su totalidad en Barcelona (España) y fue terminado en Castro (Chile).

AGRADECIMIENTOS

Comienzo agradeciendo a la editorial Marcombo, en especial a Jeroni Boixareu, que confió en mí por tercera vez. Y sobre todo a Rosa Castillo, que tuvo la gentileza de esperarme, pese a mis constantes retrasos con este proyecto. Además, doy mi más fuerte agradecimiento a Haizea Beitia por su valiosa y precisa corrección de este libro.

El apoyo familiar siempre ha sido crucial en mi vida y esta vez no fue una excepción, sobre todo teniendo en cuenta que terminé este libro junto a mi familia —estando de vacaciones—. Solo me quedan palabras de agradecimiento: primero a mi madre, luego a mis hermanas y a mis tres maravillosas sobrinas, que me regalaron sonrisas, y no menos importante, a mi abuela que jamás entenderá lo que hago. Mención especial a mis dos cuñados, que siempre guardan amabilidad para conmigo.

También agradecer a Héctor Patricio y Oscar Fernández Sierra, que tuvieron la gentileza de darme valiosas sugerencias de fragmentos presentes en este libro.

Finalmente, tengo que darles las gracias a todos mis amigos que, constantemente, me preguntaban «¿Cuándo terminas el libro?». Aprendí gracias a ellos que no hay que comentar nada sobre lo que escribes hasta tenerlo terminado.

INTRODUCCIÓN

Los conceptos fundamentales de la programación están bajo ataque. En diferentes partes del mundo, en universidades, en bootcamps, en cursos online, nuevas personas ingresan a la programación, pero no logran una comprensión profunda de ella. Mi hipótesis es que un exceso de tecnología difumina los conceptos esenciales que permiten avanzar a temas complejos en esta actividad. Necesitamos personas que puedan pensar fuera de la herramienta de moda. Este libro es un intento de dar solución a ese problema. Pero no se equivoque, este no es un libro contra las tecnologías, sino un libro que busca tener una mayor armonía con estas.

El libro que tiene en sus manos presenta una nueva forma de pensar en la programación y de entender los sistemas informáticos a través de conceptos generales, interconectados e incluso adaptativos, que llevan el nombre de principios. Algunos son técnicos, los cuales se encuentran en todas las herramientas, ya sean antiguas o modernas, fáciles o difíciles de usar; y otros son conductuales, presentes en todas las buenas relaciones humanas.

En los siguientes tres párrafos le intentaré convencer de que esta manera de aprender programación es más efectiva y productiva y, por qué no decirlo, más estimulante intelectualmente.

Primero, la programación no es una actividad aislada de las relaciones humanas, y mucho menos de sus consecuencias. Una ética es necesaria y crucial. Un informático debe ser alguien que abrace las humanidades y no una persona que se aísle en un entorno únicamente técnico. Este libro intenta aunar ambos mundos.

Segundo, considere dejar de lado los diversos «paradigmas de programación» que conoce, ya sean orientados a objeto o funcionales, imperativos o lógicos, basados en eventos o en aspectos; todos ellos dificultan el aprendizaje de lo más importante en la programación: resolver problemas.

Tercero, el beneficio derivado de estos dos puntos anteriores es que le ayudan a usted a convertirse en un mejor profesional, capaz de resolver problemas complejos técnicamente —independiente de la herramienta de turno—, y más realizado como persona. De nada sirve ser un eficaz creador de código si no puede relacionarse con sus pares o no sabe cómo comunicar su conocimiento. En suma, este libro pretende cambiar la forma en la que ve la programación.

El contenido de este libro tiene una estructura y forma un tanto inusual. Veamos los porqués.

Estructura

El libro consta de cinco tomos: Fundamentos, Principios, Sistemas, Somos humanos y Buena vida. Cada uno se puede percibir como un libro independiente, aunque con algunas interrelaciones que se pueden apreciar en la Figura 1.

Forma

Este texto difiere de los tradicionales libros técnicos, pues exploro algunos recursos ensayísticos,2 por un lado, para dar una visión personal de los temas a tratar y, por otro, para enriquecer el texto y hacer de la lectura una labor grata. Incorporo algunos recursos ficticios para explicar mejor algunos temas. Creo que esto último le ayudará a divertirse en su aprendizaje y a hacer más cercana y personal la lectura del texto.

Otro aspecto no menos importante es que, en el Tomo I, cada ejemplo de código del libro se encuentra escrito en un pseudocódigo. Los demás libros usan Python —y en pocos casos, otros lenguajes de programación—para presentar los ejemplos.

Figura 1. Los cinco tomos que componen este libro. El primero, Fundamentos; el segundo, Principios; el tercero, Sistemas; el cuarto, Somos humanos y, el último, el quinto, Buena vida.

A continuación, incluyo un breve resumen de cada libro que compone esta obra.

Resumen

Tomo I: Fundamentos

¿Cuál es la matemática necesaria que todo programador debe conocer? ¿Cuáles son los conceptos en los que se basa la programación? ¿Por qué los algoritmos y las estructuras de datos son tan importantes para aprender a programar bien? ¿Qué es el pensamiento computacional? Estas son las principales preguntas que responde este primer libro que, en pocas palabras —o en más de las que esperaba—, construye los cimientos de los libros restantes. Es la introducción técnica.

Tomo II: Principios

Es el corazón del libro. Aquí expongo un conjunto de principios técnicos y conductuales que todo profesional debe tener en cuenta para adentrarse en la programación, sin caer en la tentación de adoptar las tecnologías como un todo. Una visión agnóstica de las herramientas, que espero pueda leer con detenimiento, pues todo el libro se construye desde aquí. Algunas preguntas que se buscan responder: ¿existen principios generales de la programación? ¿Por qué un enfoque asociado únicamente a las herramientas tiene varios problemas? ¿Cuáles son las conductas que debe adoptar un buen programador para construir software y relacionarse con sus pares?

Tomo III: Sistemas

La informática es un mundo de sistemas, pero ¿cuáles son? ¿Cómo están construidos? Algunos ejemplos de sistemas son los modelos de computación, los lenguajes de programación, los sistemas operativos, las bases de datos, los sistemas distribuidos… No obstante, hay otros sistemas que en la actualidad han tomado mucha fuerza: la inteligencia artificial y la computación cuántica. Esta parte presenta una síntesis histórica de cada uno de estos sistemas, no solo para responder qué hacen, sino también cómo lo hacen.

Tomo IV: Somos humanos

Cualquier software que deba cumplir varios requisitos del cliente se vuelve intratable para una sola persona. Necesita un equipo, una metodología, una buena comunicación y buenas prácticas de desarrollo de software. Esta parte señala —haciendo uso de unos personajes ficticios— la importancia de pasar de ser un programador solitario a uno que es parte de un equipo. En esta situación otras variables entran en juego, pues la programación no es lo mismo que la ingeniería de software. Por tanto, lo que se busca tratar aquí es dar solución a las siguientes preguntas: ¿cuál es la diferencia entre programar un software pequeño (proyecto personal) y uno extenso (un equipo de decenas de personas)? ¿Qué conocimientos debo tener para desarrollar y mantener grandes proyectos de software?

Tomo V: Buena vida

No todo en la vida son cosas técnicas. En muchas ocasiones, personas brillantes con grandes conocimientos, ya sean teóricos o prácticos, fracasan en su vida profesional porque no saben relacionarse con sus colegas de trabajo o carecen de habilidades blandas. Otros fracasan porque no saben cómo mantener una vida dedicada al aprendizaje. Esta última parte, importantísima, divide los consejos en las siguientes categorías: aprendizaje, vida personal, mundo laboral y más allá de lo técnico. Quizá, al final de nuestro camino, el sueño de todo humano sea alcanzar la felicidad, tener una buena vida; por ello, cierro el libro con esto.

¿Cuál es la audiencia de este libro?

• Informáticos a los que les guste programar y quieran ampliar y replantear sus conocimientos. Tanto si son personas con pocos años de experiencias como si son personas con «muchas batallas» tras sus espaldas.

• Profesionales de otras áreas que se sientan entusiasmados por la programación. Este libro les servirá como apoyo para entender los fundamentos de la programación y, por qué no, también para comprender cuál es la esencia de la informática.

¿Qué no es este libro?

• No es un libro que le enseñe un lenguaje de programación en particular.

• No es un libro teórico, ni un libro donde hay más código que texto en lenguaje natural. Esto quiere decir que hago uso de esquemas visuales para explicar conceptos y ejemplos, todos ellos de diversa índole, pero no solo código.

• No es un libro de introducción a la programación; se espera, por tanto, que el lector tenga algún conocimiento básico de programación.

¿Qué es este libro?

• Es un libro que le enseña los fundamentos abstractos (matemática, lógica, sistemas informáticos, técnicas, etc.) necesarios para ser un mejor programador.

• Es un libro para profundizar en los fundamentos de la programación y entenderlos desde otra óptica, para poder acceder a técnicas avanzadas.

• Es un libro que da una introducción conceptual e histórica de los distintos campos de estudio de la informática, a saber, lenguajes de programación, sistemas operativos, bases de datos, sistemas distribuidos e inteligencia artificial.

• Es un libro que, a través de diálogos, le explica la relevancia de la ingeniería de software.

• Es un libro que contiene consejos para edificar una buena carrera profesional.

Para más información visite mi sitio web:

www.camilochacon.com

____________

2 Digo «libros técnicos», aunque no sé si este libro puede incluirse en esa categoría.

MAPA DE LECTURA

TOMO I

FUNDAMENTOS

La duda crece con el conocimiento.

JOHANN WOLFGANG VON GOETHE

 

«No se preocupe de la meta, sino del camino.» Al leer la frase anterior, su cerebro ha realizado una serie de complejos pasos: percibir las letras a través de sus ojos y decodificarlas, concatenarlas y formar las palabras, y para terminar darle un sentido (interpretarlas). En cierta medida se podría decir que su cerebro sabe programar.

Pero no es lo único que su cerebro puede hacer, por ejemplo, si lee las palabras «c0digo» o «progr4maci0n» notará que la primera quiere decir «código» y la segunda «programación»; su cerebro las ha corregido, reemplazando los números por las letras correspondientes, pues ya tiene asimilados patrones, que provienen de las conexiones cerebrales que se formaron una vez que usted aprendió español. Pequeñas interferencias no afectan el objetivo. Sin embargo, si el conjunto de caracteres fuera: «2i5_o» no es tan simple saber a qué término en español se refiere, podría ser ¿libro? o ¿cinco?, o quizá ¿ciclo? Se podría concluir, entonces, que no hay suficiente información como para establecer un patrón que le permita asociarlo a una palabra. Este libro trata de esto. De construir una máquina mental que le permita detectar patrones para aprender a programar. Esta primera parte le presentaré los materiales para construir dicha máquina.

La programación es una de las actividades más maravillosas de nuestro tiempo y que, si se enseña bien, debe aspirar a ser fructífera; creatividad, disciplina y rigor son algunos de sus ingredientes; en caso contrario, se puede caer en negligencia, desprolijidad y distracciones, o sea, código de pésima calidad. Esta parte busca trazar los elementos esenciales que forman los cimientos de un buen aprendizaje, de la máquina mental.

Los fundamentos son necesarios para hacer de su aprendizaje un lugar amigable y menos proclive al abandono. Conocer bien las bases de cualquier campo nos abre las puertas para profundizar en tecnologías modernas y, aunque pueda parecer paradójico —centrarse en los fundamentos (pasado) ayuda a entender las tecnologías actuales (presente)—, no lo es, pues estas nos permiten entender el cómo funcionan las cosas y no solo qué hace tal cosa.

Importante: lo que me interesa en esta obra no es que usted sea un mero usuario de tecnología; mi interés es opuesto y radical: que usted pueda construir su tecnología. Que no sea un simple usuario de sistemas, a saber, lenguajes de programación, frameworks, bibliotecas, sistemas operativos, bases de datos, etc. Más bien, mi objetivo es que tenga el conocimiento para poder producir sus propios sistemas que, a su vez, permitan generar otros sistemas. Herramientas que ayuden a otros programadores a crear herramientas.

A continuación, se realiza un breve resumen de los cuatro capítulos que completan esta primera parte del libro.

Resumen

Capítulo 1: Los fundamentos matemáticos

El capítulo está dividido en dos secciones que abarcan los siguientes temas: lógica proposicional y teoría de conjuntos; ambas son campos importantes de las matemáticas que le permitirán construir un pensamiento racional y sistemático, indispensable para aprender a programar bien y para poder sumergirse en dominios avanzados. Sin embargo, estas secciones no pretenden ser una introducción exhaustiva a cada tema, por este motivo al final de cada sección se incluyen algunas referencias.

Capítulo 2: Conceptos elementales

Un desarrollador de software debe conocer algunos conceptos básicos que son transversales a los variados lenguajes de programación. Ejemplo: funciones, recursión, condicionales, variables y bucles. El capítulo busca explicar cada uno de estos conceptos utilizando un lenguaje imperativo muy similar a Python.

Capítulo 3: Algoritmos y estructuras de datos

Un software es un conjunto de programas que están construido con algoritmos. Los algoritmos usan datos que nos permiten resolver un problema. Los datos se almacenan en estructuras de datos, que pueden ser matrices, listas o árboles, entre otras. Cómo añadir o acceder a estos datos es lo que hace diferente una estructura de datos frente a otra. Todo buen software requiere un buen conocimiento de algoritmos y estructura de datos, por un simple motivo: un algoritmo ineficiente funcionará mal independiente del lenguaje de programación que use. Un buen conocimiento de algoritmos y estructuras de datos es, tal vez, la mayor habilidad a la que aspira un programador, pues le permitirá abordar temas avanzados.

Capítulo 4: Pensamiento computacional

El pensamiento computacional es el conjunto de habilidades y conocimientos necesarios para resolver problemas utilizando técnicas y conceptos de la computación. Es —en términos simples— una manera lógica y amplia de pensar que se aplica a campos que no tienen una relación directa con la computación. Algunos ejemplos de estos campos son la escritura, la robótica o la biología.

CAPÍTULO 1

LOS FUNDAMENTOS MATEMÁTICOS

En este capítulo:

• Obtendrá una introducción a dos áreas de las matemáticas que son las raíces de la programación,3 lo que le permitirá prepararse para acceder a conocimiento más avanzado, como el estudio de algoritmos:

○ Lógica proposicional

○ Conjuntos

1.1. Introducción

Para avanzar en la programación es necesario conocer abstracciones. Y las matemáticas son una excelente puerta de entrada. Entender algunas áreas de las matemáticas abre las perspectivas de una persona y, por supuesto, las de un programador. Para diseñar e implementar programas se requiere de abstracciones que son esenciales para resolver problemas humanos.4

La primera regla del libro es la siguiente:

Conocer diversas abstracciones matemáticas facilita el aprendizaje y la construcción de herramientas.

Esta regla asume que si no conocemos ciertas abstracciones matemáticas no podemos aprender y crear herramientas de manera fácil. Tenga presente el conector «y». Nos dice que la ausencia de abstracciones de este tipo nos limita.

Ahora bien, usted se podría estar preguntando, ¿qué abstracciones matemáticas?, ¿cuándo algo es fácil de aprender? y, sobre todo, ¿qué herramientas? La primera pregunta es respondida en este capítulo. La segunda se encuentra de manera implícita en los capítulos de los Tomos II y III. La tercera será respondida en el Tomo III. Pero no se preocupe, vamos paso a paso.

Permítame defender esta regla. Un usuario de tecnología, por lo general, no requiere de matemáticas. Un programador que usa un conjunto de herramientas no exige saber cómo fue construido. No le hace falta. No tendría sentido. Pues la herramienta oculta la complejidad usando abstracciones, sin la obligación de entender cómo está construida.

Diferente es el caso de la persona que desarrolla tecnología. Pues ella necesita aunar generalizaciones, buscar patrones y cotejar la idea de simplicidad, conceptos que son matemáticos por excelencia. Así logra operar de manera exitosa con el código. Es importante mencionar que no todas las tecnologías requieren los mismos niveles de abstracción, como veremos más adelante. Por ejemplo, no es lo mismo crear una API Rest que diseñar un sistema operativo, o crear un sitio web que un lenguaje de programación (a distintos ámbitos, distintas complejidades).

Considere el último caso de ejemplo: un lenguaje de programación es una herramienta que, si está bien construida, puede cambiar —para mejor— como razonamos y construimos software. Aunque el lenguaje pueda parecer simple —en su sintaxis y su semántica—, construirlo no es una tarea sencilla ni mucho menos, pues el creador o el grupo de personas detrás de su creación han ocultado las complejidades técnicas dentro de abstracciones, para que así la vida del usuario sea sencilla de llevar.

Siendo preciso, ¿por qué tener conocimientos en matemáticas es importante para un programador?

• Por las nuevas áreas de conocimiento que están emergiendo y que desde hace ya un tiempo son una realidad. Aparte de la ya conocida inteligencia artificial, hay otras áreas como la computación cuántica, el razonamiento automático (no tan nueva, pero se han logrado grandes avances), la criptografía y los videojuegos. Por tanto, nos encontramos en un panorama que, más que abandonar las matemáticas, nos acerca a ellas, las vuelve indispensables para profundizar en temas avanzados.

• La creación de sus propias herramientas. Esto lo comenté antes y es bueno volver a recalcarlo: gran parte de los desarrollos de sistemas requieren un conocimiento teórico para comprender cómo funcionan las cosas, y la teoría, los formalismos, están irreductiblemente ligados a las matemáticas. Pensar con precisión, con detalle, con elegancia, son cualidades que hacen a cualquier profesional mejor, y más aún a un programador, cuya labor consiste en usar lenguajes de programación.

Ahora bien, ¿qué matemáticas? Como usted quizá sabe, existen muchos campos de estudio dentro de las matemáticas y no todos, como puede prever, son útiles para un desarrollador de software.

Este capítulo está organizado así: primero comenzaremos dando una introducción a la lógica proposicional. Luego explicaremos la teoría de conjunto, fundamental para entender abstracciones presentes en la programación. Finalizaremos con algunas sugerencias para seguir profundizando en otras áreas de las matemáticas que conciernen a la programación.

1.2. Lógica

Si ocurrió, puede ser. Y si ocurriera, sería. Pero como no ocurre, no es. Eso es la lógica.

Lewis Carroll

Si usted es una persona curiosa y le atrae el rigor, la lógica le gustará. La lógica no es solo un área del conocimiento con símbolos, reglas y leyes para estudiar la verdad. Es más que eso. Nos enseña a comunicarnos con cuidado y precisión, ya sea para charlar con amigos o familiares o con nuestra pareja. En definitiva, nos enseña a pensar con claridad. Así evitamos contradicciones o ambigüedades.

Muchos libros sobre lógica no incluyen suficientes ejemplos prácticos. A menudo, comienzan presentando las reglas y lo que se puede o no hacer con la lógica, pero no profundizan en cómo aplicar estos conceptos más allá de la programación.

Un ejemplo: la lógica nos ayuda a dar un discurso ordenado, nos ayuda a estructurar mejor lo que escribimos, nos ayuda a comprender mejor lo que leemos, nos ayuda a no realizar gastos innecesarios porque podemos cotejar mejor diversas alternativas… En suma, nos ayuda a tomar mejores decisiones en todos los ámbitos de nuestra vida.

A continuación, mostraremos cómo la lógica proposicional se aplica a situaciones cotidianas a través de ejemplos de análisis del lenguaje.

1.2.1. Lógica proposicional

Toda afirmación puede considerarse una oración, pero no toda oración es una afirmación. Una oración es una afirmación si puede ser verdadera o falsa, por ejemplo: «Los perros tienen cuatro patas», «Chile es un país» o «Hay humanos de cuatro metros de altura». Estas tres oraciones son una afirmación porque se pueden responder de manera afirmativa o no. Una afirmación siempre debe tener un valor de verdad.

Sin embargo, no toda oración es siempre una afirmación, a saber: (a) «¿Qué es la vida?», (b) «Se me cayó el libro», (c) «Me encanta sentir la brisa». Ninguna de las tres oraciones anteriores puede ser verdadera o falsa; (a) amerita una respuesta que no es verdadera o falsa, (b) depende del contexto, quizá a mí se me cayó un libro pero a usted no, (c) es una sensación y no una afirmación, por tanto, no es verdadera ni falsa.

A una oración afirmativa le llamaré enunciado.

Por otro lado, hay casos donde un enunciado no es una afirmación:

(1) Ella está enferma.

(2) El coche tiene una avería.

(3) Yo tengo el cabello largo.

Cada uno de los enunciados anteriores puede responderse como verdadero o falso (aunque depende de lo que conozca cada persona). En (1) el pronombre «ella» es confuso porque no se sabe a quién se refiere; en (2), ¿a qué coche se refiere? y en (3) es más probable que sea verdadero para una mujer que para un hombre y, en todo caso, el «yo» es ambiguo.

Hay muchas palabras en una oración que pueden añadir ambigüedad, es el caso de los pronombres «ella», «él», «yo» u otras como «ahí», «aquí», «Nuri», «José», «libro»… Para cada uno de estos ejemplos puede existir más de una respuesta dependiendo de a quién le preguntemos. ¿Cuántas personas tienen el nombre Nuri o José? Muchas. ¿Cuántos libros existen? Bastantes. Así que para evitar malentendidos con sus interlocutores tenga presente esto al momento de comunicarse.

Pero, incluso si quitamos esta imprecisión, pueden existir afirmaciones que son verdaderas o falsas a la vez:

(4) El reino de Prusia existe.

(5) El Imperio romano se mantiene activo.

(6) Derek Parfit está vivo.

La afirmación (4) fue verdad entre 1701 y 1918, en la actualidad es falsa; (5) fue verdad entre 27 a. C. y 476 d. C., que son las fechas en que surgió y cayó el imperio romano; en lo que respecta a la (6), el filósofo Derek Partif5 murió el 1 de enero de 2017, por tanto, en la actualidad es una afirmación falsa. Puede advertir que hay afirmaciones que pueden ser verdaderas o falsas, todo depende del momento en qué se comprueben.

La afirmación «Camilo Chacón Sartori vive en España» es ahora verdadera, pero seguro que en los próximos 90 años será falsa (pues aún no ha encontrado la pócima de la vida eterna).

1.2.1.1. Tablas de verdad

Las operaciones lógicas se pueden representar con una tabla de verdad. Una tabla de verdad acepta dos tipos de operaciones: unaria o binaria. Las dos usan estados binarios: verdadero o falso. La operación unaria cambia el valor de un estado a otro (por ejemplo, el conectivo «no»). La operación binaria trabaja con dos estados (por ejemplo, el conectivo «y» o «si … entonces …»).6

La tabla de verdad es útil para entender cómo funcionan las conectivas lógicas. Y su simpleza radica en que solo trabaja con estados binarios. Así podemos comprobar los valores de verdad de una manera visual e intuitiva.

Comencemos con una operación básica, la unaria.

Si tenemos dos estados, verdadero (V) y falso (F), entonces la negación es una operación unaria:

Son unarias porque requieren un único estado de entrada para generar el resultado. Este conectivo invierte el estado del valor de entrada. Al mismo tiempo, es posible crear una «cadena» de operaciones de negación:

y

En los dos ejemplos anteriores hay un patrón: cuando la cantidad de operaciones de negación es un número impar y se aplica a un estado, entonces el estado se invierte; en otro caso, el estado se mantiene.

Seguimos con las operaciones binarias.

Conjunción. Esta trabaja con dos estados de entrada y devuelve un único estado.

Es verdadero si los dos estados de entrada son verdaderos; en cualquier otro caso, es falso.

Disyunción. Al igual que la conjunción, la disyunción también requiere de dos estados de entrada. No obstante, a diferencia de la conjunción, solo requiere que al menos un estado sea verdadero para que el resultado sea verdadero,

Condicional. Algo que lo diferencia de los dos anteriores conectivos binarios es que existe una «dependencia» entre el primer estado y el segundo. Cabe recordar que el conectivo condicional se traduce como «si … entonces …».

Bicondicional. A diferencia del anterior –condicional– este conectivo solo devuelve un valor verdadero cuando ambos estados son iguales. Se traduce como «si … y solo si …».

1.2.1.2. Conectivos lógicos

Los conectivos lógicos nos permiten unir diferentes enunciados. De momento, sepa que hay cinco principales:

Los he escrito en español. No obstante, para tratar con operaciones lógicas es preferible usar símbolos:

A cada una de estas conectivas lógicas se las conoce como conjunción (^), negación (~), disyunción (⌄), condicional (→) y bicondicional (↔).

1.2.1.3. Oraciones simples

Si necesitamos manipular la misma oración varias veces, es conveniente usar un símbolo que la represente, al igual que hicimos con las conectivas lógicas. Así, las oraciones (1)-(3) quedarían de este modo:

1.2.1.4. Oraciones complejas

Una oración compleja es una oración compuesta. Y una oración compuesta contiene – por definición– más información que una oración simple. En este caso se pueden mapear usando los conectores lógicos:

(1b) Ella está ENFERMA y debe regresar a CASA

(2b) El coche tiene una AVERÍA o te has EQUIVOCADO

(3b) No tengo el cabello LARGO

(3c) Si tengo el cabello LARGO, entonces debo CUIDARLO

(1c) Ella está ENFERMA si y solo si se siente MAL

Así, cada una de estas oraciones compuestas se puede escribir en un lenguaje simbólico (también llamado formal):

Siempre hay que tener en cuenta casos como el siguiente:

No es lo mismo que:

La anterior es similar a escribir: ~ (L ^ C).

Sin embargo, las dos anteriores tampoco equivalen a:

Estos ejemplos dan muestra de que los paréntesis nos ayudan a evitar confusiones.

Conjunción

Hay afirmaciones que pueden concatenarse o unirse. Así logramos obtener más información sobre lo que estamos hablando. Dos ejemplos:

(7) Cada lenguaje de programación tiene una sintaxis y tiene un nombre.

(8) Bollocks es un bar de rock y se encuentra en Madrid.

En (7) hay dos afirmaciones: «cada lenguaje de programación tiene una sintaxis» y «tiene un nombre»; vemos que la forma de unir dos oraciones es con el conector «y». Lo mismo ocurre en (8), «Bollocks es un bar de rock» y «se encuentra en Madrid». Para términos práctico utilizaremos el símbolo «^» para referirnos al conector «y». Las oraciones quedan de la siguiente manera:

• Cada lenguaje de programación tiene una sintaxis ^ un nombre

• Bollocks es un bar de rock ^ se encuentra en Madrid

Una conjunción es verdadera si todas las afirmaciones son verdaderas. Otra manera de decirlo es que, si hay al menos una afirmación falsa, todo lo demás será falso. Según mi experiencia, no conozco ningún lenguaje de programación sin una sintaxis y menos sin un nombre; por tanto, la conjunción sería: verdadero ^ verdadero, que es igual a verdadero. En cambio, según mi experiencia en ambientes de rock, el Bollocks es un bar de Barcelona y no de Madrid; entonces quedaría del siguiente modo: verdadero ^ falso, que es igual a falso.

Negación

Una afirmación también puede negarse o cambiar su resultado. Una oración como «Derek Parfit no está vivo» sería una negación de (6). Podemos cambiar el «no» por el símbolo «~» al comienzo de la afirmación. Esta oración queda de la siguiente manera:

(9) ~ Derek Parfit está vivo

Se recomienda añadir paréntesis cuando hay múltiples conectores para evitar ambigüedades y confusiones. Si modificamos (8), obtenemos:

(10) ~ (Bollocks es un bar de rock) ^ se encuentra en Madrid

Sin agrupar las afirmaciones con paréntesis el resultado sería distinto:

(11) ~ Bollocks es un bar de rock ^ se encuentra en Madrid

Aunque este caso (11) no es equivalente al siguiente:

(12) ~ (Bollocks es un bar de rock) ^ ~ (se encuentra en Madrid)

Cuando se desea negar más de dos elementos se puede usar «no … ni …» o «ni … ni …». Si modificamos (7), quedaría:

(13) No hay lenguaje de programación con una sintaxis ni con una semántica ni con un nombre.

(14) Cada lenguaje de programación, ni tiene sintaxis, ni una semántica, ni un nombre.

(13) es una modificación de (7) que usa la estructura «no … ni …» en cuanto añadí una negación, «ni con una semántica»; en cambio, en (14) se mueve el sujeto al principio de la oración para poder hacer negaciones múltiples con «ni … ni …». Ambas, (13) y (14), son equivalentes para el efecto de negación.

Disyunción

Hay ocasiones donde podemos expresar más de una alternativa en una oración. Por ejemplo, oraciones que tengan la estructura «o … o …» o «hay … o …» nos dicen que algunas de las alternativas pueden ser verdaderas. La única forma de que el resultado sea falso es que no haya ninguna opción verdadera (todas falsas). La disyunción es distinta a la conjunción porque no necesita que todos sus elementos sean verdaderos para que el resultado sea verdadero. La disyunción puede construirse a través de la conjunción (^) y la negación (~).

Si tenemos la afirmación «A Nuri le gusta escribir, leer y bailar», entonces para que sea una disyunción haremos lo siguiente:

(15) ~ (~A Nuri le gusta escribir ^ ~leer ^ ~ bailar)

Además, hay dos tipos de disyunciones: inclusiva o exclusiva. La primera asume que al menos dos afirmaciones son verdaderas, pero cuando es exclusiva, significa que solo una es verdadera. En (15), si asumimos que Nuri es alguien «alegre», tendríamos que solo la primera y la segunda afirmación son verdaderas, a saber: «le gusta escribir y leer». «Le gusta bailar», sin embargo, sería falsa, y obtendríamos la forma «verdadero o verdadero o falso». En cambio, si Nuri es «aburrida» únicamente la última afirmación sería verdadera: «me gusta bailar». Por tanto, sería una disyunción exclusiva, logrando la forma «falso o falso o verdadero».

También puede ver que si a Nuri no le gusta escribir, ni leer, ni bailar, entonces (15) será falsa.

Otras conectivas: «pero», «aunque» y «a menos que»

Hay otros ejemplos que surgen cuando usamos palabras como «pero», «aunque» o «a menos que». Si nos fijamos en nuestras conversaciones diarias, podemos apreciar que tendemos a contrastar lo que decimos, a relativizarlo o a poner de antecedente algo que consideramos. Véanse los siguientes ejemplos:

(16) Neus pinta, pero Laura toca el piano.

O de otra forma:

(17) Neus pinta, aunque Laura toca el piano.

Ambas afirmaciones, (16) y (17), son similares y pueden ser reemplazadas usando el conector «y»:

(18) Neus pinta y Laura toca el piano.

Cuando, por un lado, aparece un «pero», se enfatiza un contraste corriente y, por otro, «aunque» es una oposición que puede ser parcial, pues matiza una afirmación previa. 52ara efectos prácticos, si una afirmación es verdadera, ambas pueden ser reemplazadas con la conjunción «y». Otro caso:

(19) Neus debería pintar, a menos que Laura toque el piano.

La afirmación anterior (19) quiere decir que Neus va a pintar en caso de que Laura no toque el piano; dicho de otro modo, si Laura toca el piano, entonces Neus no va a pintar. O sea, para que (19) sea verdadera debe tener la forma «verdadero ^ ~falso» o «~falso ^ verdadero».

Condicional

Hay afirmaciones que pueden depender de otras (a diferencia de la conjunción, en donde cada afirmación tiene igual peso de importancia). Por ejemplo, en dos conjunciones de modo «verdadero ^ falso» o «falso ^ verdadero», no importa el orden de los elementos, el resultado seguirá siendo el mismo: falso. El caso del conector condicional es diferente: sí importa el orden. El conector condicional, como su nombre lo dice, condiciona una afirmación dentro de una oración según un orden. Su forma es «si … entonces …».

(20) Si soy programador, entonces soy feliz.

Para alguien puede que (20) sea cierto, en la medida en que programar le puede aportar felicidad, pero no tiene por qué ser así. Si el antecedente «soy programador» es verdadero y el consecuente «soy feliz» es falso, entonces esta afirmación es falsa; en cualquier otro caso (son tres), sería una afirmación verdadera. Tenga presentes los conceptos antecedente y consecuente para referirnos a la parte inicial y final de una afirmación.

Para el condicional es común usar el símbolo «→»; entonces, la estructura «verdadero → falso» es falsa. Ahora bien, como mencionamos en el párrafo anterior, cualquier otra alternativa es verdadera: «verdadero → verdadero», «falso → verdadero», «falso → falso».

Hay varias cosas interesantes con este conector: (1) siempre que el antecedente sea falso la afirmación será verdadera y (2) cuando el consecuente sea falso y su antecedente sea verdadero, se dará el caso de que la afirmación es falsa.

Por otro lado, en el lenguaje natural la forma idiomática «si … entonces …» puede tener otras variantes —modificando (20) —:

• Soy feliz si soy programador.

• Soy feliz siempre que sea programador.

• Soy feliz en caso de que sea programador.

• Si soy programador es suficiente para ser feliz.

• Si soy programador implica que soy feliz.

•No soy programador a menos que sea feliz.

Todas estas variantes idiomáticas son equivalentes a (20) en cuanto a su forma «si … entonces …». Algo a tener presente es que el condicional nos ayuda a analizar la noción de razón suficiente y condición necesaria. Tomemos un enunciado como el siguiente:

(21) Soy escritora, entonces escribo.

Aquí el antecedente «soy escritora» es razón suficiente para afirmar que escribe, pues supone que cualquier escritora lo es por el simple hecho de escribir. Asimismo, el consecuente «escribo» es una condición necesaria para que sea escritora; de otro modo, si nunca ha escrito, no puede ser escritora.

Bicondicional

El conectivo bicondicional se diferencia de la condicional porque la relación entre el antecedente y el consecuente es más fuerte. Hay una relación de equivalencia y su forma es «si … y solo si …». Un enunciado será verdadero si ambos valores son idénticos: «verdadero ^ verdadero» o «falso ^ falso». En cualquier otro caso, el enunciado sería falso.

Considere el siguiente enunciado:

(21) Paula sabe programar si y solo si escribe código.

Es evidente que cualquier persona que sepa programa debe haber escrito algo de código. Pero si invirtiéramos el orden del enunciado no sería bicondicional:

(22) Escribe código si y solo si Paula sabe programar.

En este caso el antecedente «Escribe código» es genérico y podría no referirse a Paula, por tanto, no tiene sentido, pues cualquiera podría escribir código sin necesidad de que Paula sepa programar.

El bicondicional usa el símbolo «↔» y se puede derivar de la relación de las siguientes conectivas:

Lo visto hasta aquí es nada más una pincelada de la capacidad que tiene la lógica para darnos mayor claridad en lo que expresamos y, por consiguiente, en cómo pensamos. Espero le haya activado su curiosidad por saber cómo construir enunciados de manera lógica pueda mejorar sus comunicaciones.

Al final de este capítulo le sugerimos revisar las lecturas recomendadas para ahondar en otros temas de la lógica, por ejemplo, la lógica de primer orden y de segundo orden.

1.3. Conjuntos

Para poder adentrarse en cualquier literatura de informática, con cierto interés y predisposición a la teoría, es imprescindible tener un conocimiento de teoría de conjuntos. No hace falta que sea profundo, aunque sí lo suficiente para poder entender la nomenclatura. ¿Por qué? Pues porque para definir algoritmos es necesario una notación compacta, breve, que nos permita entender lo que hace un método sin entrar en los detalles de la implementación, a saber, el algoritmo desarrollado en un lenguaje de programación «real». Esos detalles de implementación no son necesarios para la especificación. Y una de las herramientas para esta especificación es usar conjuntos matemáticos.

Un conjunto es un objeto matemático que permite la construcción de cualquier otra estructura matemática. Es, por así decirlo, una colección de objetos. Esos objetos pueden ser tangibles o intangibles. Ejemplo: un portátil, una persona o un libro son objetos tangibles; un número, una figura geométrica o el fichero de un ordenador son intangibles.

En esta introducción solo trataré las operaciones básicas de los conjuntos, no así su área de estudio, conocida como «teoría de conjuntos», pues esta contiene propiedades y axiomas que no vienen a cuento ni son necesarios para nuestra empresa (al final de este capítulo puede encontrar recomendaciones de libros para ahondar en este tema).

1.3.1. Notación

Cuando un elemento existe en un conjunto se utiliza el símbolo de pertenencia ∈. Así, 3 ∈ 𝐴 y 2 ∈ 𝐴. Pero, en cambio, 1 no es elemento de 𝐴; entonces: 1 ∉ 𝐴, ya que 1 es parte de uno de los elementos de 𝐴 que es un conjunto (1 ∈ {1,5}), pero no es parte de 𝐴. Entonces podemos decir:

𝑥 ∈ 𝐴significa que 𝑥 es un elemento de 𝐴;

𝑥 ∉ 𝐴significa que 𝑥 no es un elemento de 𝐴.

Ejemplo 3. A menudo un conjunto consiste en elementos que satisfacen una propiedad. Por ejemplo:

1.3.2. Subconjunto

Dado:

Todos los siguientes ejemplos son válidos:7

Los conjuntos son parte importante en construir el aparataje mental necesario para acceder a conocimiento avanzado en programación, esto es, la lectura de artículos científicos y otros materiales que definan algoritmos de manera formal. Al final de este capítulo encontrará algunos textos sugeridos para profundizar en este campo.

1.4. Conclusión

La programación no es matemática, pero la matemática ayuda a avanzar a temas más avanzados de programación. Esta distinción, crucial, es importante, pues programar no se reduce a una capacidad lógica para resolver problemas: conlleva una cierta habilidad para usar un computador, saber investigar (conocer las fuentes dónde aprender), resolver problemas (por ejemplo, cuando no puede instalar una biblioteca y tiene que arreglar problemas de dependías), un pensamiento computacional (puede revisar el capítulo que lleva el mismo nombre)… Sin embargo, las matemáticas ayudan a construir un aparataje abstracto, necesario para construir software avanzado —a saber, áreas de ciencias o matemáticas— y entender el hardware.

1.4.1. Lecturas sugeridas

Las obras que recomendamos en este apartado no solo se centran en los temas tratados en este capítulo, sino también en los temas que, por espacio, no pudieron añadirse.

Lógica

•The Art of Logic: How to Make Sense in a World that Doesn't de Eugenia Cheng. Un maravilloso libro de divulgación sobre cómo aprovechar el conocimiento de la lógica en quehaceres cotidianos. Escrito con gran lucidez y creatividad. Se lo recomendamos como paso previo a los dos libros siguientes.

•Elementary Logic de Willard Van Orman Quine. Una extraordinaria obra que, a pesar de los años en que fue publicada, sigue siendo maravillosa para iniciarse en la lógica proposicional.

•How Logic Works: A User's Guide de Hans Halvorson. Un libro actual que, además, entrega un aire fresco a los libros de lógica.

Matemáticas discretas

•Mathematical Structures For Computer Science de Judith L. Gersting. Un completo libro sobre todas las matemáticas necesarias para un programador.

Estadísticas y probabilidades

•Essential Math for Data Science: Take Control of Your Data with Fundamental Linear Algebra, Probability, and Statistics de Thomas Nield. Una amena introducción a las matemáticas necesarias para el aprendizaje automático, con énfasis en las probabilidades y estadísticas.

____________

3 No son las únicas; por ejemplo, las estadísticas y probabilidades y las estructuras discretas son también relevantes en la programación. No obstante, por un tema de espacio las hemos omitido. De todas formas, para suplir esto hemos añadido lecturas recomendadas al final del capítulo.

4 En el libro Elements of programming de Alexander Stepanov y Paul McJones, se examinan en profundidad las abstracciones requeridas por un programador, un ingeniero y un científico, que trabajan en distintos roles de la informática. No obstante, este libro, que recomiendo fuertemente, asume que el lector debe tener una madurez en las matemáticas; es más, utiliza C++ como lenguaje vehicular en todos los ejemplos del libro, lo cual podría alejar a personas que nunca han usado dicho lenguaje. Por otro lado, solo presenta aspectos técnicos, sin tratar los aspectos conductuales. De todas formas, es uno de los grandes libros —avanzados— que se han escrito sobre informática en los últimos años y, sin duda, nos ha influido.

5 Fue un filósofo británico que trabajó en el tema de la identidad y la moral de las personas. Una de sus obras principales y que recomiendo leer es Razones y personas.

6 La tabla de verdad fue introducida por el lógico polaco Emil Post (1897-1954) y por el filósofo austriaco Ludwig Wittgenstein (1889-1951) en su obra magna, Tractatus Logico-Philosophicus.

7 Quizá el ejemplo que más le sorprende es ∅ ⊂ 𝐴, pues por convención todo conjunto tiene de subconjunto un conjunto vacío ∅. ¿Cómo se explica? Una forma de verlo es encontrar un contraejemplo: para que ∅ ⊂ 𝐴 sea falso, significa que hay un elemento en ∅ que no existe en 𝐴, pero dado que el conjunto vacío no tiene elementos, entonces se asume que es verdad.

CAPÍTULO 2

CONCEPTOS ELEMENTALES

En este capítulo:

• Aprenderá algunos conceptos fundamentales que están presentes en la programación, divididos en dos grupos: secuenciales y funcionales.

• Comprenderá como estos dos grupos de conceptos se pueden integrar.

2.1. Introducción

Toda área de conocimiento requiere de conceptos.

Los conceptos son abstracciones que nos permiten comprender un comportamiento o cosa desde, en muchos casos, el entendimiento de otra. O sea, hay conceptos que tienen distintos niveles de jerarquías, que nos pueden ayudar más o menos, dependiendo del contexto en que los utilicemos. Así, un concepto puede derivar de uno o más conceptos. La programación no es la excepción. Hay varios conceptos que rondan en este ecosistema. En este capítulo trataremos aquellos que viven en dos grupos: los secuenciales y los funcionales. En los conceptos secuenciales encontramos a las variables, los condicionales y los bucles, y en los conceptos funcionales a las funciones y a las recursiones. Todos ellos se pueden encontrar en los lenguajes de programación, lo único que cambia —si nos permite decir eso— es la importancia que se le da a uno u otro. ¿Por qué, si es que hay un motivo, se eligieron estos conceptos y no otros? Por un lado, porque se pueden encontrar en diversos lenguajes de programación, modernos o antiguos, compilados o interpretados, fáciles de usar o enrevesados, y por otro, porque han sobrevivido al paso del tiempo gracias a su utilidad —en informática, el sobrevivir al paso del tiempo es un buen predictor de eficacia—.8

Luego de tratar los conceptos secuenciales y funcionales, daremos una breve comparación de ambos conceptos. Concluiremos con algunas reflexiones sobre la importancia de estos conceptos en programación.

2.2. Secuenciales

En la programación hay expresiones que permiten realizar cálculos de manera secuencial, paso a paso, de manera explícita. Esto quiere decir que sintácticamente se puede ver cómo se realiza cada cálculo sin capas de abstracción.

En este apartado le mostraré tres casos típicos de expresiones secuenciales: variables, condicionales y bucles.

2.2.1. Variables

Detrás del concepto de variable subyace una idea más profunda que simplemente asociar un valor a un nombre: trata de una abstracción. Algo que ya vimos en el capítulo anterior de lógica. ¿Se acuerda de que un enunciado puede ser simplificado al nombre de una variable? Por ejemplo, el enunciado «Si escribo, puedo ser programador o escritor» se puede descomponer en dos partes: «Si escribo» sería «A» y «puedo ser programador o escritor» es «B». En la lógica no importa tanto el significado de las frases como su forma. Entonces, a dicho enunciado lo trataremos como un condicional: «A → B» (véase el capítulo anterior de lógica en caso de dudas). Eso nos abstrae de las complejidades del lenguaje natural y, así, operaremos sobre ese enunciado usando tan solo «A» y «B».

A diferencia de la lógica —en particular de la lógica de predicado—, una variable no solo indica una simplificación de un enunciado en un lenguaje natural, sino que también puede almacenar cualquier valor que luego es representado en un ordenador. Y como un ordenador trabaja en su nivel más elemental con números binarios (sección anterior), cualquier formato sería permitido, desde su año de nacimiento hasta su vídeo predilecto.

Las variables nos permiten reducir la complejidad al igual que cualquier otra abstracción. Imagínese por un momento que tiene el siguiente mensaje:

312938012ADASHDKJH32132ASPX

A menos que usted sea algún tipo de alienígena llegado desde una galaxia lejana, dudo que pueda saber qué significa dicho mensaje; pero antes de descubrir su significado, es prioritario recordarlo para volver a usarlo. Si lo quiere volver a usar tendría que valerse de su propia memoria (humana). Quizá usted es de las pocas personas que todavía recuerda los números de los móviles de sus familiares o amigos, pero el mensaje anterior presenta aún más retos. Para empezar, tiene más caracteres y es alfanumérico (o sea, acepta números y letras). Podría hacer la prueba: lea el mensaje y luego escríbalo en algún papel intentando recordar cada carácter, en el orden correcto, usando su memoria…

¿Cómo le fue? ¿Lo recordó con 100% de exactitud, sin errores? Me temo que no. Lo mismo ocurre en la programación: necesita almacenar datos complejos en términos simples. Así llegamos a las variables, abstracciones que nos dan soporte para evitar memorizar datos complejos.

2.2.1.1. Declaraciones

Los programadores, al igual que la mayoría de los humanos, no tienen una memoria prodigiosa. Por tanto, requerimos un soporte que nos permita manejar esta complejidad.

Un lenguaje formal es una manera de reducir esta complejidad. Considere la siguiente expresión:

clavePersonal := 312938012ADAKJH32132ASPX

Esta significa «la variable clavePersonal tiene asignado el valor 312938012ADAKJH32132ASPX». El símbolo de asignación es el «:=».9 Ahora bien, ya no nos debería importar más ese complejo mensaje iniciado con «31293…», sino el nombre de la variable: clavePersonal. Desde ahora podríamos acceder a ese enrevesado valor. ¿Es mucho más simple recordar clavePersonal que dicho valor, no cree?