Máquina abstracta
¿Qué es?
Computadora digital que ejecuta algoritmos los cuales están formalizados para que la maquina entienda.
Se trata de una maquina abstracta porque estamos aislando las características de una computadora para llevarlas a este concepto. La estructura general de una maquina abstracta es que tiene una memoria donde almacena datos y sus programas, además tiene un interprete del lenguaje de programación que maneja las secuencias de control del programa, controla la transferencia de datos y además maneja su memoria. Para realizar operaciones que nos darán un resultado que será la instrucción que deseamos y lo que resulta de estas instrucciones.
Puede realizar operaciones para:
Ciclo de ejecución
Al ser algo conceptual tanto su estructura como ciclo de ejecución, es el mismo para todas.
Primero inicia el programa, se traen las instrucciones a través del intérprete del lenguaje, el cual las decodifica, trae sus operandos y elige que operación ejecutará. Si la operación 1,2,3 o 4. O incluso puede ser el caso en el que se fuerza a detener la ejecución del programa. Si se elije una operación que lleva más procedimientos, esto traerá resultados, los cuales se almacenan en la memoria de la maquina y se vuelve a repetir el ciclo.
La maquina de Turing:
Es un ejemplo de maquina abstracta, han existido muchas replicas y la maquina de Turing lo que hace, es que tiene 2 cintas en cada lado y en el centro tiene un dispositivo lecto escritor, es capaz de leer o escribir sobre él mismo, en los rodillos hay instrucciones, indicadas con números 1 y 0. Puede indicar que escriba, lea, etc. En un punto profundo, podemos entender que la maquina de Turing, realiza los procesos que vimos antes.
Lenguajes de programación vs Lenguaje natural
Un lenguaje lo usamos entre humanos para comunicarnos, expresar nuestros sentimientos, o incluso de forma colaborativa para llegar a un fin.
En las computadoras, nosotros usamos un lenguaje de programación para decirle qué hacer, cómo hacerlo, a través de qué recursos. Algunos lenguajes permiten ser especifico con las instrucciones.
La computadora no comete errores, nosotros dimos mal las instrucciones.
¿Qué es un lenguaje?
Estilo y modo de hablar y escribir de cada persona en particular.
Lenguaje de programación
Un lenguaje de programación es un formalismo artificial en el cual los algoritmos pueden ser expresados.
Niveles de descripción
Gramática Responde a ¿Qué oraciones son las correctas?
Semántica Responde a ¿Qué significan las palabras?
Pragmática Responde al ¿Cómo usarlos?
Implementación
Es la forma en que se transforman esas instrucciones en acciones.
¿Qué son los paradigmas de programación?
Teoría o conjunto de teorías cuto núcleo central se acepta sin cuestionar y que suministra la base y modelo para resolver problemas y avanzar en el conocimiento
Basado en sus características y entendiendo que existen lenguajes multiparadigma.
Por su forma de abordar un problema o herramienta utilizadas.
Smalltalk → P.O.O
Haskell → Funcional
C++, Java, JavaScript, Scala, PHP, Python, Ruby, F#, etc.
¿Qué significa tener un paradigma?
Prohibir o limitar ciertas acciones:
Principales paradigmas de programación
→Por procedimientos
→Orientado a objetos
→Fortran, Java, C, Python, Ruby, PHP, etc.
→Funcional
→Lógico
→Matemático
→Reactivo
→Prolog, LISP, Haskell, SQL, Elixir, XPath, Regex, etc.
Programación estructurada
Inicialmente los programas eran escritos línea a línea, siendo secuencial, podían haber programas con 5.000 líneas.
Origen
A mitad de los años 40 se reconoció que un programa y sus datos podían residir en la memoria de una computadora.
Arquitectura de Von Neumann
Se trata de una maquina que tiene un dispositivo de entrada, los procesa, tiene una unidad de control donde maneja memoria, después nos da una salida de da una salida de datos.
Estructuras de control
En 1968 Dijkstra advirtió el daño de la expresión “GOTO”. La expresión GOTO se indicaba para saltar de una línea a otra.
<h1>Programación funcional</h1>Es un paradigma que usa funciones como “Ciudadanas de primera clase”. Puede crear funciones de orden superior. Prioriza el uso de recursividad y HOF para resolver problemas.
Una función puede recibir y dar salidas a otros datos como resultado, incluyendo a otras funciones. Se busca eliminar o reducir los efectos secundarios.
Origen
En los años 30, Alonzo Church desarrolla el cálculo Lambda. Alan Turing demuestra que este es el equivalente a las maquinas de Turing.
A finales de los 50, se desarrolla LISP, implementando la notación lambda de Church.
Dato curioso
La saga de video juegos Jack and Daxter, fueron desarrollados en GOAL (Game Oriented Assembly Lisp). Está basado en Lisp, fue desarrollado con programación netamente funcional.
(print"Hello, World!")
(defun factorial (n)
(if (= n 0) 1
(* n (factorial (- n 1)))))
Funciones
Relación entre dos conjuntos que asigna cada elemento del primero un elemento del segundo o ninguno.
En matemáticas una función es algo similar:
Un tipo de dato u objeto que toma un valor “X” y genera un valor “Y”
Puede o no devolver un resultado.
f(X) = X + 3
f(X) = X^2 + 3
Aquí tenemos el ejemplo de una función en python. Toma dos parámetros y nos va a retornar como resultado, la suma de ambos parámetros.
def suma (a, b)
return a + b
def suma (a, b):
a + b
operacion_1 = suma(3, 2)
Ciudadanas de primera clase
Son reconocidas por el lenguaje, se utilizan como un tipo de dato y en cualquier parte del programa.
Funciones de orden superior
Es una función que puede:
Funciones puras
Funciones lambda
Es común escucharlo cuando hablamos de programación imperativa. Lo podemos ver cuando manejamos funciones o variables de contexto global o que están delimitadas. Ej: En JavaScript es muy importante tener un manejo del SCOPE (alcance de las variables)
Cuando escribimos código sabemos que lo que esta dentro de una función, no afecta a otra, si es que usamos la sintaxis correcta. Pero también existen funciones que utilicen parámetros o que tengan alcance global y puede tener efectos secundarios.
Forma en que alguien o algo se comporta ante un determinado estímulo.
Cambios observables
Como podemos ver, aquí está la función que se llama a sí misma y solamente modifica los parámetros cuando lo hace, como característica hay muchos paréntesis, pero es simplemente parte de la sintaxis.
(defun factorial (n)
(cond
((= n 0) 1)
((= n 1) 1)
(t (* n (factorial (- n 1 ))))))
Tenemos en Haskell donde calculamos el factorial de un número, en ejemplos anteriores habíamos podido ver como se define el tipo de dato, después se asignan los tipos de valores y se empieza a llamar a la función. Podemos ver que el código no es tan amplio como si lo hubiéramos escrito de forma no recursiva con otros lenguajes.
module Main whereimport Text.Printf
factorial :: Integer -> Integerfactorial0 = 1factorial n = n factorial (n - 1)
line x = printf "%d! = %d\n" x $
factorial x
main = mapM_ line [0..16]
Aquí también tenemos un ejemplo con F# que es un lenguaje funcional y vemos que también es recursivo porque la función factorial se está llamando a sí misma.
letrec factorial n =
match n with
| 0 | 1 -> 1
| _ -> n * factorial(n-1)
<h1>Programación lógica</h1>
¿Qué es la programación lógica?
Paradigma declarativo que expresa los objetivos como una colección de afirmaciones o reglas acerca de los resultados y restricciones en lógica matemática.
Áreas de aplicación
Cláusula de Horn
La programación lógica se basa en las clausulas de Horn las cuales son preposiciones definidas por predicados, donde tenemos un hecho (algo que damos por sentado) y tenemos uno o varios predicados, lo correcto sería tener por lo menos 2, para poder determinar si algo es verdadero o falso, también se les conoce como cuerpo/body.
H= Hecho/Head of the rule.
P= Predicado/Body
Ejemplo:
Podemos decir que es verdadero que está nevando en la ciudad, C es el nombre de la ciudad. Si está lloviendo y hace frío, entonces es verdadero que está nevando. Y por el contrario si quisiéramos negar que está lloviendo, pero hace frío, entonces es falso que está nevando. Esto tiene una estrecha relación con las tablas de verdad.
nevando© ← lluvia©, frío©
Origen
Se origina en los 60’s cuando Cordell Green propuso el uso de cláusulas en programas a finales de los 60.
Prolog impulsó este paradigma.
Lenguajes
No es muy frecuente este paradigma de programación en la industria, se usa más para investigación y cuestiones académicas, dada su naturaleza.
% Hola mundo
?- write('Hello World!'), nl
> HelloWorld!
> true
En este ejemplo podemos ver como le indicamos que hay personas que hablan un lenguaje, hacemos la evaluación de la persona 1 con la persona 2 y cuál es el resultado. Luego hacemos también la evaluación, preguntando “Quién habla francés” El resultado retornado debería ser “Juan”
speaks(juan, french)
speaks(isabel, english)
speaks(eduadro, french)
speaks(eduardo, english)
talkswith(Person1, Person2) :-
speaks(Person1, L),
speaks(Person2, L),
Person1 \= Person2
?- speaks(Who, French)
<h1>Programación dirigida por eventos</h1>
Se caracteriza porque no controla la secuencia de ejecuciones, reacciona a los sucesos ocurridos.
Generalmente los programas corren indefinidamente integrando manejadores de eventos (event handlers).
Eventos
Casos de aplicación
Cómo funciona
Sí lo comparamos con la programación imperativa, tenemos una secuencia de pasos que se van a ejecutar de manera secuencial y después puede repetirse el ciclo o puede llegar a detenerse el programa porque así lo decidimos o porque forzamos su detención. En la programación dirigida por eventos, tenemos un ciclo que puede ser un while el cuál mientras haya una condición sea verdadera o falsa, se puede estar ejecutando de manera indefinida. Entonces este ciclo va a recibir ciertos eventos que van a modificar algunas variables de estado, que puede ser como el caso de un videojuego, el contador de vidas, en el cual la condición dice que mientras que el número de vidas sea mayor que 0, se va a estar ejecutando el programa, pero habrán ciertos eventos que van a hacer que ese número de vidas disminuya o aumenten y por consecuencia el videojuego termine en ese ciclo.
Lenguajes
Java
Javascript
C#
Librerías/Frameworks de GUI
-JavaFX, React.js, PyQT
Prácticamente cualquier lenguaje orientado a objetos.
Analogía: Imagina ser el propietario de una panadería, mientras se calienta el horno, estás cortando masa, cortándola, preparándola y una vez que se están horneando, al sacarlos hay que esperar a que se enfríen y después colocar una cobertura de chocolate. Tú intentarás optimizar los recursos, mientras el horno se está calentando, debes preparar más masa, para que así, cuando termine, inmediatamente meter el otro lote de masa o si contratas a una persona que te ayude, dividirás las tareas, al hacer esto, estás ejecutando el paralelismo, que es dividir las tareas entre los recursos disponibles, siempre y cuando puedan dividirse.
Concurrencia
Coincidencia, concurso simultáneo de varias circunstancias.
Es cuando hay una serie de peticiones a un mismo recurso que podría ser limitado y se están atendiendo esas solicitudes de forma parcial o totalmente desordenada. Una analogía útil para entender, puede ser la panadería, imagina que tu panadería empieza a crecer y a ser muy grande, por lo tanto es bastante concurrida y los clientes empiezan a acumularse, por lo tanto, tú no puedes atenderlos a todos, empezarían a enojarse por no ser atendidos de forma rápida y ordenada. Una forma de solucionarlo, podría ser un sistema de tickets, para así atender a los clientes en su orden de llegada.
Concurrencia vs Paralelismo
En la concurrencia
tenemos una serie de peticiones con un solo recurso limitado para atenderlos, ¿Cuál sería el orden, la prioridad? etc.
En el paralelismo
Tenemos recursos divididos que pueden atenderlos de forma simultanea sin ningún problema
El paralelismo y la concurrencia, son conceptos diferentes pero que van de la mano, por ello debemos entender ambos para entenderlos entre sí.
Secuencia vs Concurrencia
En una secuencia
Vamos a tener los pasos A, B, C, D. Y estos serán atendidos en el orden que se hizo la petición.
En la concurrencia
Podemos iniciar en el proceso A, saltar al D, luego al C, completar el A y después pasar al último proceso.
Todo esto se hace mediante los hilos de un procesamiento
Estados de un hilo
Sección crítica del hilo
Es una sección de código que requiere acceso exclusivo a una variable compartida.
Comunicación entre hilos
Carreras (Critical races)
Sucede cuando dos o más hilos desean acceder a un recurso lo más pronto posible. Podemos ver este ejemplo, tenemos una variable C, inicializamos en 0, pero después en alguna parte del código a C, le asignamos el valor de C + 1, entonces un hilo llegará primero y al ver que vale 0, le agregará el valor de 1, almacena ese dato y ahora C vale 1. Pero sí otro hilo llega después, pensará que C vale 1, entonces añadirá otro 1, almacenará ese dato y entonces C vale 2. Esto puede ser un problema en un sistema automatizado de dosificación de medicamentos. Sí el sistema es concurrente, ¿Entonces que hará? ¿Le dará una dosis o dos dosis? ¿Cómo se resuelve?.
Puntos muertos (deadlock)
Ocurre cuando un hilo espera por un evento que nunca sucederá.
Para que suceda un punto muerto deben de cumplirse 4 condiciones:
Problema de los filósofos
El problema plantea que hay una mesa redonda donde hay 5filósofos que están conversando, frente a ellos hay un plato de comida, a su derecha y a su izquierda, hay otros filósofos y hay un palillo chino a la derecha y otro a la izquierda, para comer se necesitan ambos palillos chinos, eso significa que habrá una persona que no comerá. Hay muchas formas de abordar el problema, pero esas soluciones pueden dar otros problemas, podría ser un sistema de turnos, pero entonces algunos se quedarían esperando hasta que la comida esté fría o tenga mucha hambre. Podríamos hacer que se alternen los turnos de comida.
Estrategias
Evitar que se cumpla alguna de las condiciones
Los monitores tienen 4 componentes principales:
Algunos lenguajes
Década de los 40: primeras computadoras y lenguajes ensambladores.
La primer computadora no fue una maquina abstracta, eso es un concepto teórico, sin embargo, sabíamos que las computadoras épocas atrás, tenían tamaños enormes, ocupaban canchas de tennis, trabajaban con switches.
Hay distintos criterios para definir cuál fue la primer computadora y algunos autores mencionan que fue la EDSAC. Sus características:
Las precursoras
Carecían de herramientas lingüísticas para ser programadas al nivel de la EDSAC.
Iniciaron con código máquina, llamados first-generation languages (1GL)
Lenguajes ensambladores
Década de los 50: Fortran y Algol
Los lenguajes de alto nivel son lenguajes abstractos, ignoran las características físicas de HW y se expresan como algoritmos. Third generation languages (3GL).Cuando hablamos de lenguaje ensamblador nos referimos a uno específico. Esta afirmación es: