**Intro a Pharo**
# Introducción:
Información en migración y en Spanglish: Este es un documento en migración, que retoma información del 2016, escrita originalmente como libreta interactiva en Grafoscopio y se está adecuando a nuevas tecnologías de Lepiter, surgida hasta 2021. En ese sentido, intenta recuperar y migrar información de los contextos originales en los que fue concebida, aprovechando los nuevos desarrollos tecnológicos, al tiempo que da cuenta de aquellas visiones y preocupaciones que no están reflejadas en esos nuevos entornos, pero que sí estaban en los originales. Por ejemplo: la preocupación por una mirada crítica a los datos y el código y la formación de capacidades al respecto, de modo que el código sea más un lenguaje común en lugar de un bien exclusivo a los desarrolladores de software y a sus preocupaciones. Un código que refleje sujetos y mundos más plurales. Por ello, en la medida en que da cuenta de los orígenes históricos y sus transiciones, también irá adaptándose a esto nuevos contextos. Mientras tanto, se notarán algunos elementos en Spanglish, pues el documento original estaba concebido para varios talleres internacionales, pero ahora se usa en clases y procesos de facilitación principalmente en el pregrado de Ciencias de la Información, Bibliotecología y Archivística, así como en los talleres recurrentes mixtos, que ocurren en remoto y en el hackerspace HackBo, de la comunidad de Grafoscopio. Próximas visitas a este documento deberían dar cuenta de su evolución. Te agradecemos de antemano por participar de esta transición en tu rol de lector(a)/explorador(a), por tu papel proactivo y tu paciencia al respecto.
# Interacción Básica
## Inspeccionando y Haciendo
Es un Do It que abre un inspector sobre el resultado de evaluar la expresión que has seleccionado. El Inspector es una herramienta que le permite echar un vistazo al interior de un objeto. Por ejemplo, seleccione el texto a continuación, abra el menú y haga clic en 'inspeccionarlo (i)':”
*Hace una operación que se podría considerar matemática, pues divide 1 por 2.*
Intenta ALT-i (or CMD-i or CTRL-i) en las siguientes expresiones:
*Es un expresión que condiciona el comando para que muestre la fecha y la hora de hoy, es decir, la fecha actual que maneja el sistema del computador. *
*Según la interpretación hecha, muestra el número 𝝿 en el valor matemático que este tiene. También, nos da el valor númerico en otras expresiones como: binario, decimal, exponente y significante.*
*Esta es una expresión que muestra la versión actual de Pharo que se esta utilizando, en un comentario que hace se puede entender que hace un seguimiento de todas las actualizaciones y que también es llamada en el inicio automático para obtener todos los complementos más recientes. *
## Imprimiendo
Hablemos de impresión. Es un Do It que imprime el resultado junto a la expresión que has seleccionado. Por ejemplo, seleccione el texto a continuación, abra el menú y haga clic en 'imprimirlo (p)':
*Cuando se oprime 'imprimirlo (p)' se ejecuta la operación predispuesta, para este caso es el resultado de la suma. Con **ctrl + p** se puede ejecutar la acción imprimir de la operación anterior. *
¿Has visto la letra 'p' entre paréntesis junto a 'imprimirlo'? Indica el acceso directo ALT- (o CMD- o CTRL-) para ejecutar este comando. Pruebe ALT-p (o CMD-p o CTRL-p) en las siguientes expresiones:
*Cuando realizo lo indicado en el enunciado, se ejecuta lo escrito en la expresión. Es decir, enseña la fecha actual que esta en el sistema.*
*Al ejecutar **ctrl + p** se muestra la hora exacta, cada se ejecute **ctrl + p** teniendo las expresiones seleccionadas, se actualizará la hora.*
El resultado está seleccionado, por lo que puedes borrarlo usando la tecla de retroceso.
*La expresión anterior enseña la versión actual Pharo, exactamente la versión de **SmalltalkImage**, el resultado impreso con el comando, se puede borrar porque queda seleccionado después de proceder con **ctrl + p** . *
# Tipos Básicos: representando datos
Los tipos básicos son formas de representar información dentro de este sistema. Ver nodos en el interior para más detalles.
## Números
Ahora sabes cómo ejecutar el código Pharo. Ahora hablemos de objetos básicos. 1, 2, 100, 2/3... son Números, y responden a multitud de mensajes evaluando expresiones matemáticas. Inspeccione estos:
*Calcula el factorial de 20 y nos muestra las distintas representaciones del número: decimal, hexágonal, octal, binario, bytes, kilobytes, megabytes...*
*Resuelve la expresión matemática mostrada anteriormente, encuentre el factorial de 1000 y lo divide por el factorial de 999, devolviendo como resultado **1000**. *
*Opera la división de la fracción anterior, divide **1** por **3** y da como resultado **0,3**. *
*Resuelve la operación matemática, sumando las fracciones. Obteniendo: **17/15**, posteriormente da el resultado de la división entre **17** por **15** resultando **1,3**. *
*Aquí se resuelve la operación matemática, pero tiene una cualidad y es que posee la expresión **asFloat**, y es evidente que esto genera un resultado diferente a una operación sencilla. Se observa que con la nueva culidad agregada da el resultado solo, como un número flotante sin mostrar lo anterior.*
## Caracteres
Un caracter represetan una letra o glifo del alfabeto y puede ser creado o instanciado usando el operador $
*Crea la letra A como caracter y como un número perteneciente a la tabla **ASCII** .*
Puedes encontrar cuál es el número ASCII de un carácter.
*Con la ejecución del anterior comando, obtuvimos el valor de **@** en la tabla **ASCII**. No sólo se crea un caracter sino que con la función **charCode** se imprime el valor que tiene lo anterior en un lugar especifíco (Tabla ASCII). *
Hay algunos caracteres que no son imprimibles.
*Esta función no se imprime, por el contrario retorna a el texto y escribe lo mismo que depositamos anteriormente.*
*Con esta función sucede algo similar a la anterior, no se imprime sino retorna al texto depositado en un principio.*
Puedes imprimir todos los 256 caracteres del código extendido ASCII
*Con la anterior función se podrían observar todos los caracteres de la tabla **ASCII**, sin embargo, hay algunos caracteres que no se muestran debido a problemas de visualización.*
Si ve palabras sin sentido es debido a algún problema de visualización con símbolos no romanos/latinos, generalmente causado por las fuentes que ha instalado en su sistema operativo y la interacción con un sistema Pharo/GT.
## Cadenas
Un String o cadena es una colección de caracteres. Usa comillas simples para crear un objeto String. Inspecciona estas expresiones
*Con al función anterior se muestra una cadena de ancho de 8 bytes , se deposita con **ByteString** cuando se imprime.*
*Crea los primeros 256 caracteres de forma única, trayendo como resultado que todas las instancias de caracteres latinos sean idénticas. *
*Crea una cadena (**string**) con el texto **PharoTutorial**, cada letra predispuesta con un **`$`** para formar su código **ASCII** .*
**Conjunto de posiciones donde pongo valores individuales.**
*Aquí nos da el número **13**, debido a que este es el número de caracteres con el que cuenta el texto **PharoTutorial**.*
*La anterior función tiene la característica de que convierte las letras minúsculas a mayúsculas y las transforma en una cadena (**string**) con su **$** para formar su código **ASCII**. *
*Cuando se ejecuta, devuelve el texto de reverso. *
*Esta función es igual a la anterior, cumple el mismo cometido. La única excepción es que este texto es un palíndromo.*
Puedes acceder a cada caracter de una cadena usando el mensaje at:
*Accede directamente al caracter que se este expresado, para este caso va hacia la posición **6** que es la **T**. Cuando se ejecuta es la que se muestra.*
La concatenación de String usa el operador coma:
*Crea dos cadenas (**string**) o colleciones en una lista con los textos **PharoTutorial** e **is cool**.*
*Esta función une tres textos, separados por comas para formar una nueva lista: **Pharo tutorial is cool when i active the code**.*
## Símbolos
Un símbolo (Symbol) es una cadena (String) única globalmente. Hay uno y solo un símbolo #PharoTutorial. Pueden existir varios objetos de tipo cadena (String) cuyo contenido sea 'PharoTutorial' (Message=retorna 'true' si los dos objetos son IGUALES)
*Esta función convierte el texto **PharoTutorial** en un **Symbol** (debido a que tiene el comando **as** que es **como** ).* Se analizó que las expresiones de **símbolo** son únicas, por lo que sí este comando no existe antes, se creará uno.
*Como se vio anteriormente, este comando convierte el texto **PharoTutorial** es una cadena (con el comando **as** ).*
*Verificó si los dos objetos son iguales, debido a que corresponden al mismo, expresó: **true**.*
*Esta evaluando si ambos textos son iguales, debido a que son distintos en contenido expresa: **false**. *
*Esta haciendo una evaluación si ambos textos son iguales, expresó que son iguales en contenido, pero existe una negación lógica porque la **mayoría** de mesajes están configurados como **códigos de bytes** y evitan la **sobrecarga del envío de mensajes completos. *
**Dos como cadena, agarre el caracter $2. Dos como cadena termina en el mismo lugar que el dos como cadena**
*Hace la comprobación de igualdad, la cual es correcta porque cada **símbolo** es único globalmente.*
## Arreglos
Los arreglos son maneras de guardar colecciones de información diversa. Los hay de dos tipos, estáticos y dinámicos. Acá veremos los primeros. Los arreglos estáticos, o simplemente arreglos, son aquellos en los que los valores de todos los objetos que los conforman son conocidos en el momento en que el arreglo se define (es decir, no contienen cálculos o variables, como los dinámicos que veremos más adelante). Los arreglos están confinados por #( ) y sus elementos se separan por espacios. Por ejemplo, inspecciona la siguiente expresión, que define un arreglo de 3 elementos
*Ejecuta los 3 elementos.*
Inspecciona las siguientes expresiones:
*Ejecuta y expresa el número total de arreglos que tiene la función: **4** arreglos. El primero es el número **1**, el segundo el número **2**, el tercero el número **3** y el cuarto los comandos **#(456)**.*
*Al ejecutar la función, expresó: **false**, debido a que el arreglo contiene elementos.*
*Esta función se va directamente hacia el **primer** elemento del arreglo, para este caso es el número **1**.*
**Corrección.**
*Modifica el **segundo** elemento de la expresión por **Pharo**.*
## Arreglos Dinámicos
Los arreglos dinámicos son creados durante el tiempo de ejecución. Es decir, que podemos guardar en ellos cálculos, que luego se ejecutarán y determinarán el valor específico de lo que en ellos se guarda. Están confinados por llaves { } y sus elementos se separan con el caracter ".". Inspecciona la siguiente expresión para definir un arreglo dinámico
*Los arreglos tienen consignados en ellos cálculos, al ejecutar resuleve estos cálculos y los resultados se ponen dentro del arreglo dinámico.*
Comparemos este arreglo estático
La coma se toma como arreglo.
con este arreglo dinámico:
Separa elementos del arreglo.
*Cuando se ejecuta esta función se obtiene el tamaño **total** del arreglo dinámico.*
## Collecciones e iteradores
Una colección es un arreglo o secuencia de datos (ordenados o no y repetidos o no). Un itereador es un elemento que recorre cada uno de los elementos de la colección. Hagamos un ejemplo previo para entender las colecciones. Una colección que duplica los primeros 20 números:
*Hace una colección de **1** a **20** y cada uno lo duplica.*
En la parte interna del bloque estoy usando un iterador, que he llamado each y está antes de la barra (|) y una instrucción each * 2, que está después de la barra.
*Hace una colección de **1** a **20**. pero le hace un incremento de 2 (**by: 2**) a cada número de la colección. Y luego le suma a cada número **3**.*
Cuando usamos el mensaje #collect: lo que hacemos es que realizamos una operación en todos los elementos de la colección, como vimos en los ejemplos previos. Sin embargo, cuando usamos #select: lo que hacemos es creamos una nueva subcolección, cuyos elementos son aquellos que satisfacen una condición, es decir, que al aplicarles un proposición, dicha propición es verdadera.
*Se crea una subcolección del **1** al **20** donde los número pares **satisfacen** una condición, por lo tanto se les aplica la propición y se muestran en la ejecución.*
De un modo similar, el mensaje #reject: rechaza todos los elementos en los que la condición sea verdadera. Por ejemplo:
*Se crea una subcolección de números **impares** y **rechaza** todos lo elementos donde la condición sea verdadera. *
# Mensajes: procesando datos Los mensajes son la forma en que los objetos se comunican entre sí y en que nosotros, los humanos, nos comunicamos con el sistema de cómputo. Hay tres tipos de mensajes: unary (unarios), binary (binary) y keyword.
## Unario
Los mensajes unarios tienen la forma siguiente. anObject aMessage Tu ya has enviado mensajes unarios. Inspecciona los siguientes mensajes unarios:
*Al ejecutar la función, esta devuelve a el objeto **1** su clase, que es la clase inmediata: **SmallInteger**.*
*Devuelve al objeto **#b** su clase, que es la clase **ByteSymbol**. *
*Devuelve al objeto **$b** su clase. que es la clase **Character**.*
*Se obtiene su negación, por ello expresa al ejecutar la función: **false**.*
## Binario
Los mensajes binarios tienen la forma siguiente: anObjecto aMessage anotherObject Puedes inspeccionar los siguientes son mensajes binarios:
*Resuelve la operación matemática.*
*Realiza la operación matemática y con el igual compara si el resultado es correcto.*
*Realiza la suma de **3** semanas a la fecha actual del sistema.*
*En lugar de hacer una suma a la fecha actual, **resta** 3 años y da el resultado.*
*Se puede reescribir como **false OR false**, lo cual tendrá como consecuente: **false**.*
*Reescribiendo sería: **true OR false**, lo cual tendrá como consecuencia: **true**. *
*Se reescribe como: **true AND false**, y tedrá como resultado: **false**.*
*Al ejecutar la función, resuelve indicar en el plano cartesiano; para el **eje x:** 10 y para el **eje y:** 100. *
*Resuelve correctamente la operación matemática.*
*Cuando se ejecuta, expresa: **false**, debido a que la fecha actual no es menor que la de el día de ayer.*
## Keyword
Los mensajes 'keyword' son mensajes con argumentos. Tienen la siguiente forma: anObject akey: anotherObject akey2: anotherObject2 Inspecciona los siguientes mensajes keyword:
*Al ejecutar la función es **verdadera**, ya que **4** esta entre **0** y **10**.* +
El mensaje lo que nos dice es: si (4) esta entre (0 y 10) cuya respuesta es verdadero, pero si cambio el valor del 0 por 3, el resultado es falso
*El resultado de esta función es el número **mayor** entre los dos números expresados.*
determina el valor máximo entre dos números.
*Aquí se obtendra el **color** que contenga el valor máximo. *
El mensaje es r:g:b: implementado en la clase Color. Note que también puede escribir
Si quieres usar código RGB usando valores de 0 a 255, como es la práctica usual, deberás escribirlos como cociente, de forma que sean un número entre 0 y 1. Por ejemplo r: x/255 g: y/255 b: z/255, donde x,y,z son los valores entre 0 y 255 correspondientes al código que color que queremos obtener.
## Prioridad
Los mensajes unarios son ejectuados primero, los mensajes binarios son ejecutados despues y finalmente las cadenas de mensajes: paréntesis > Unary > Binary > Keywords
*Como se ejecuta primero el unario, se procede a establecer como **negativo** al **2:** -2. Luego, el binario y como se pide **aumentar** el número **3** a **2** se ejecuta la operación: **9**, finalmente se hace la operación final y se enseña el resultado. *
**Se interpreta de izquierda a derecha. Si no hay paréntesis se hace de izquiera a derechar. Si hay paréntesis, se hace primero el paréntesis**
*Se ejecuta la operación entre paréntesis: **5** y luego exponenciamos **5** veces al **2** (según la función **raisedTo**) para tener como resultado: **32**.*
*Se hace la creación de un **punto** en el plano cartesiano, para posteriormente asignarle la clase a ese punto:**Point**. *
*Se crea un área rectangular en la pantallas, las funciones de rectángulo crean nuevas instancias determinando las intersecciones. Posteriormente se define la clase: **Rectangle**. *
Entre mensajes de procedencia similar, las expresiones son ejectuadas de izquierda a derecha
*Primero se denomina el **valor absoluto** de **-3** (3), para luego aplicar el valor negativo nuevamente: (**negative**) -3.*
### Cambiando la prioridad de los mensajes
Usar parentesis cambia el orden de evaluación de la sentencia, primero se ejecuta la parte interna() y posteriormente la sentencia
### Prioridad de los mensajes matemáticos
Las reglas tradicionales de las matematicas NO aplican dentro de Pharo.
*No se ejecuta primero la suma, sino que se hace la multiplicación, obteniendo como resultado el **20**. Posteriomente se le suma **2**.*
Aqui el mensaje multiplicación (*) es enviado al 2, y su resultado correspondiente es 20. Entonces 20 reciben el mensaje +, con argumento 2, para un total de 22. Recuerda que todos los mensajes simpre siguen una regla precente de izquierda a derecha, sin excepciones.
## Mensajes en cascada
Supongamos que tenemos un objeto donde queremos mostrar un conjunto de resultados
*Se **limpia** todo, esto se puede **entender** con el grafico de la **basura**.*
Y enviamos esta secuencia de mensajes:
Enviar cada uno de los mensajes, refiriéndose individualmente al objeto receptor de los mismos es engorrosso. Para hacer lo mismo de manera abreviada usamos el operador en cascada ";", que usado para enviar mensajes al mismo receptor. Así, una vez limpiemos el Transcript anterior
podemos verificar que enviar cada uno de los mensajes anteriores es igual a:
**Defines una secuencia de mensajes que le quieres enviar al mismo objeto**
## Bloques
Ahora hablemos de los bloques. Piensa en los bloques como una manera de 'congelar' código que luego podremos ejecutar por demanda, cuando queramos y/o las condiciones para su ejecución se cumplan. Los bloques son métodos anónimos, lo cual quiere decir que no es necesario ponerles nombres para invocarlos (como ocurre con las operaciones sobre objetos que hemos visto hasta el momento) y pueden pueden ser almacenados en variables. Los bloques están delimitados por paréntesis cuadrados: []
**Código congelado, no lo ejecuta**
**Para ejecutar un bloque se debe poner la función: *value*.**
El bloque anterior no abre el Zen de Pharo, porque el bloque, por omisión, no es ejecutado. Ahora ejecuta:
Acá hay otro bloque que suma 2 a su argumento (su argumento se llama x):
*Aquí el argumento es **x** y la parte que decide es **x+2**.*
Los argumentos, son las variables internas de los bloques, están precedidas por ':' y la barra vertical "|" separa la parte en que se definen los argumentos, de la parte en que se dice que hacer con ellos. Podemos ejecutar un bloque enviandole mensajes value
**Aquí se ejecuta el bloque con *value*.**
*Aquí el argumento es **5** y esta dividido en **2** (x/2) para ser convertido en una ejecución **flotante** (asFloat).*
*Aquí el argumento es **10** y se le suma **2** (x+2) para obtener como resultado: **12**.*
Podemos tener además bloques que reciban varios argumentos, por ejemplo
*Aquí se tienes **dos argumentos**, el **3** y el **5**. Estos dos números se restan, para obtener el resultado de **-2**.*
## Asignación de bloques
Los bloques pueden ser asignados a variables y ejecutados después. Nota que |b| es la declaración de una variable llamada 'b' y que ':=' asigna un valor a una variable. Selecciona las siguientes tres líneas e imprimelas (Print it)
## Condicionales
Los condicionales son sólo menajes enviados a objetos Boolean (booleanos)
*Si cumple la condición ejecute la primera línea, de lo contrario la segunda. En este caso, se hizo la primera porque es **verdadero**.*
Aquí el mensajes es ifTrue:ifFalse Prueba esto:
*Si **3 = 3** se aplica el siguiente comando.*
## Ciclos e Iteradores
Los ciclos con iteradores de alto nivel sobre las colecciones, implementados como métodos regulares.
1 to: 10 = do: lo que quiero hacer :i
¿Qué hacer cuando necesito tanto el índice como el objeto? En ese caso usamos doWithIndex, que permite trabajar con los objetos y con su índice, es decir, tener bloques que reciben dos argumentos.
*Ejecuta un orden para una colección , agreaga los colores según la descripción. Después según el comando, se muestra el **número** del color y el **nombre** del color.*
### Colecciones
El mensaje do: es enviado a una colección de objetos (Array, Set, OrderedCollection), evaluando el bloque para cada elemento. Acá queremos imprimir todos los números sobre el Transcript (una consola)
*Muestra cada elemento en la colección y se supone que multiplica a **cada uno** por **2**, sin embargo, en la colección no se aplica la respectiva multiplicación.*
Algunos otros iteradores realmente buenos.
*Se crea una nueva colección con el **valor absoluto** de cada número.*
*Se crea una nueva colección en donde se dispone **true** si el número es impar y **false** cuando el número sea par.*
*Aquí en esta colección solo están los números **impares**.*
*En la siguiente colección solo se predisponen los números **iguales** o **mayores** que **10**.*
*Aquí se ponen los números que **no son mayores que 10**.*
*Cada número de la colección debe estar separado por un punto.*
*Busca en los arreglos un número que sea **igual a cero** con lo cual enseñaría un enunciado: **Encontrado**, de lo contrario muestra **nil**.*
# Opciones avanzadas
Las siguientes lecciones son algo más avanzadas y referidas a elementos de interfaces gráficas (botones, morphs) y cambios en caliente en los métodos de Smalltalk. Si bien son importantes, las exploraremos con detalle en otros lugares, así que puedes pasar al cierre de este tutorial y luego ir a otros nodos como los de código elegante en Pharo y otros ejemplos minimalistas para terminar en los distintos proyectos del nodo titulado “Visualización de datos”.
## Ejemplos con botones
Los objetos son instancias de sus clases. Usualmente, enviamos el mensaje #new a una clase para crear una instancia de esta clase. El mensaje #allInstances enviado a una clase, responde un arreglo con todas las instancias de esta clase. Por ejemplo, miremos cuántas instancias de SimpleButtonMorph existen, imprimiendo la siguiente línea:
*Nos dice que la cantidad es **0**, sin embargo, la cantidad en bytes de las instancias es **31**. También, se puede apreciar cómo construir una instancia y sus partes.*
Ahora creemos una nueva instancia de él
Con la creación de las nuevas instancias, se muestra las específicaciones requeridas.
Ves el botón centrado en el mundo? La lista de todas las instancias debería contener una instancia más
Juguemos con él:
Borrémosla y pidámosle al sistema limpiar la memoria:
Haz click sobre el botón para ir a la siguiente lección:
## Cambiando un sistema vivo en ejecución
Puedes inspeccionar y cambiar el sistema en tiempo de ejecución. Mira el código fuente del método #ifFalse:ifTrue: de la clase True:
O sólo su comentario:
Acá están todos los métodos que implementa el ProfStef, base de este notebook:
Creemos un nuevo método para ir a la siguiente lección:
## Limpiando métodos
Antes de ir más allá, removamos este método:
## Explorando objetos
Pharo está lleno de objetos. Hay ventanas, texto, números, fechas, colores, puntos y mucho más. Puede interactuar con objetos de una manera mucho más directa que con otros lenguajes de programación. Cada objeto entiende el mensaje "explorar". Como resultado, obtienes una ventana del Explorador que muestra detalles sobre el objeto.
Esto muestra que el objeto de fecha consta de un momento (inicio) y una duración (un día).
Verás, la clase tiene muchos objetos. Echemos un vistazo a mi código: