WEBVTT

00:00:00.440 --> 00:00:04.440 align:middle
En esta sesión, hablaremos
sobre iteradores y colecciones.

00:00:04.600 --> 00:00:09.000 align:middle
Veremos como recorrer fácilmente las colecciones
Gracias a los iteradores en Pharo.

00:00:09.160 --> 00:00:13.000 align:middle
Entenderá
El poder de los iteradores en Pharo.

00:00:13.160 --> 00:00:17.640 align:middle
Revisaré los iteradores principales
que puede utilizar.

00:00:17.800 --> 00:00:19.360 align:middle
Un primer ejemplo

00:00:19.520 --> 00:00:22.680 align:middle
este es el código
que debería escribir en Java

00:00:23.880 --> 00:00:25.320 align:middle
para recorrer una colección

00:00:25.480 --> 00:00:28.160 align:middle
Exploraré las personas de la colección.

00:00:28.320 --> 00:00:31.920 align:middle
Para extraer la lista de personas
(objecto Persona).

00:00:32.480 --> 00:00:35.240 align:middle
En Pharo, escribiría este código.

00:00:35.400 --> 00:00:39.880 align:middle
Usaría el iterador collect:
Hablaremos de el más tarde.

00:00:40.040 --> 00:00:43.360 align:middle
Recoge todos los nombres de personas.

00:00:43.520 --> 00:00:47.920 align:middle
Por cierto, en Java 8,
la última versión de Java

00:00:48.080 --> 00:00:51.120 align:middle
Han presentado los bloques,

00:00:51.280 --> 00:00:53.640 align:middle
el equivalente de cierres léxicos.

00:00:53.800 --> 00:00:57.000 align:middle
Como resultado, la sintaxis
se acerca a Pharo.

00:00:57.160 --> 00:01:00.200 align:middle
Pero en Pharo, lo hemos tenido
desde el comienzo.

00:01:00.360 --> 00:01:02.440 align:middle
Está en el corazón del idioma.

00:01:02.600 --> 00:01:07.320 align:middle
Da gran poder de expresión.
a un programador

00:01:08.200 --> 00:01:11.320 align:middle
Hay muchos iteradores.

00:01:11.480 --> 00:01:16.400 align:middle
Primero, hay "collect:" ¿cual es el uso
de "collect:" cuando se envía a una colección?

00:01:16.560 --> 00:01:20.240 align:middle
Esta es una colección
de números positivos y negativos.

00:01:20.400 --> 00:01:23.200 align:middle
Envío el mensaje "collect:",
y paso un bloque

00:01:23.360 --> 00:01:25.560 align:middle
Cada vez que navega por la colección,

00:01:25.720 --> 00:01:30.160 align:middle
el parámetro del bloque
será a su vez: 2, -3, 4, etc.

00:01:30.320 --> 00:01:33.760 align:middle
Luego envía el mensaje abs,
para absoluto

00:01:33.920 --> 00:01:36.840 align:middle
Significa que quieres el valor absoluto
de este numero

00:01:37.000 --> 00:01:40.720 align:middle
Una vez que haya aplicado el bloque
a cada elemento de la colección,

00:01:40.880 --> 00:01:43.360 align:middle
agrega los resultados en una nueva colección.

00:01:43.520 --> 00:01:46.520 align:middle
El resultado devuelto por collect
Es una nueva colección.

00:01:46.680 --> 00:01:50.160 align:middle
El bloque se ha aplicado
a cada elemento de la colección:

00:01:50.320 --> 00:01:53.800 align:middle
el valor absoluto de 2,
el valor absoluto de -3, que es 3,

00:01:53.960 --> 00:01:58.480 align:middle
el valor absoluto de 4, 4,
el valor absoluto de -35, 35.

00:01:58.640 --> 00:02:00.320 align:middle
y el valor absoluto de 4, 4.

00:02:01.080 --> 00:02:04.200 align:middle
Lo interesante
que debe recordar

00:02:04.360 --> 00:02:06.760 align:middle
es que debe pensar en el objeto.

00:02:06.920 --> 00:02:09.720 align:middle
Pedimos a la colección
hacer algo por nosotros

00:02:09.880 --> 00:02:14.440 align:middle
La colección
navega por sus propios elementos por sí misma.

00:02:14.600 --> 00:02:17.240 align:middle
Proporcionamos el procesamiento
de cada elemento

00:02:17.400 --> 00:02:20.400 align:middle
Ahí es donde está el secreto
de los iteradores.

00:02:21.040 --> 00:02:23.280 align:middle
Este es otro ejemplo de "collect:"

00:02:23.440 --> 00:02:27.000 align:middle
Esta es una colección
a la que envío el mensaje "collect:"

00:02:27.160 --> 00:02:31.000 align:middle
En el bloque, preguntaré cada vez

00:02:31.760 --> 00:02:34.200 align:middle
si el elemento es inpar.

00:02:34.360 --> 00:02:37.160 align:middle
Voy a agregar todos los resultados

00:02:37.320 --> 00:02:40.080 align:middle
false, true, false, true.

00:02:43.720 --> 00:02:47.480 align:middle
Por supuesto, puede escribir

00:02:47.640 --> 00:02:50.400 align:middle
lo que normalmente escribiría
en otros idiomas

00:02:50.560 --> 00:02:52.680 align:middle
sin bloques e iteradores.

00:02:52.840 --> 00:02:55.160 align:middle
Podría escribir: tomo la colección,

00:02:55.760 --> 00:02:58.680 align:middle
construyo una colección de resultados.

00:02:59.320 --> 00:03:03.560 align:middle
Recorro desde uno
al tamaño de la colección.

00:03:03.720 --> 00:03:04.960 align:middle
Usaré do

00:03:05.120 --> 00:03:08.920 align:middle
Recorro la colección
y cada vez lo agrego a la colección de resultados.

00:03:09.080 --> 00:03:12.400 align:middle
Puedes escribir todo esto.
Es exactamente lo mismo.

00:03:12.560 --> 00:03:15.440 align:middle
Tu decides.
¿Quieres escribir algo simple?

00:03:15.600 --> 00:03:19.000 align:middle
o algo complicado?
Esa es la pregunta.

00:03:19.160 --> 00:03:22.000 align:middle
Prefiero la primera solución.

00:03:24.200 --> 00:03:27.120 align:middle
En la jerarquía
de las colecciones Pharo,

00:03:28.320 --> 00:03:32.000 align:middle
hay algo crucial:
todas las colecciones son polimórficas

00:03:32.160 --> 00:03:35.080 align:middle
y heredan de la clase Collection.
Entonces tienes una API común.

00:03:35.240 --> 00:03:39.720 align:middle
La ventaja es que los iteradores
también funcionaran

00:03:39.880 --> 00:03:42.840 align:middle
con la mayoría de colecciones.

00:03:44.480 --> 00:03:48.080 align:middle
Realmente se trata de pensar en un objeto:

00:03:48.240 --> 00:03:51.280 align:middle
le pide a la colección
Iterar sobre sus elementos para nosotros.

00:03:51.440 --> 00:03:54.800 align:middle
No sabemos si
estamos usando un diccionario.

00:03:54.960 --> 00:03:58.880 align:middle
No queremos saber sobre la lógica
interna de claves, valores, etc.

00:03:59.400 --> 00:04:02.320 align:middle
Entonces le pide a la colección que se recorra

00:04:02.480 --> 00:04:04.960 align:middle
y procese sus elementos.

00:04:06.640 --> 00:04:11.320 align:middle
Se pueden usar muchos iteradores para hacer esto.
Ya vimos "do:" y "collect:"

00:04:11.480 --> 00:04:14.280 align:middle
Hay mas:
"select:", "reject:", "detect:", etc.

00:04:14.440 --> 00:04:17.840 align:middle
Estudiaremos algunos de estos
Más adelante en este curso.

00:04:19.320 --> 00:04:22.760 align:middle
"do:" es el iterador más simple.

00:04:22.920 --> 00:04:26.960 align:middle
Navega por todos los elementos de la
colección, lo muestro en el Transcript.

00:04:27.120 --> 00:04:30.560 align:middle
Ya lo vimos muchas veces.

00:04:30.720 --> 00:04:33.320 align:middle
Este es un nuevo iterador, "select:".

00:04:33.480 --> 00:04:36.560 align:middle
Quiero obtener todos los elementos
de la colección

00:04:36.720 --> 00:04:38.360 align:middle
que coinciden con un criterio.

00:04:38.520 --> 00:04:41.960 align:middle
Quiero todos los elementos inpares
de la colección

00:04:42.120 --> 00:04:45.040 align:middle
Envío "select:" a la colección.

00:04:45.200 --> 00:04:46.440 align:middle
Paso un bloque

00:04:46.600 --> 00:04:49.560 align:middle
Siempre que el valor del bloque sea true,

00:04:49.720 --> 00:04:53.080 align:middle
el elemento involucrado
se agrega a la colección de resultados.

00:04:55.040 --> 00:04:58.080 align:middle
Es exactamente lo mismo que "select: #odd"

00:04:58.240 --> 00:05:01.120 align:middle
Cuando tengo un bloque aquí

00:05:01.280 --> 00:05:05.400 align:middle
o lo que equivale mensaje unario de envío
al elemento de la colección,

00:05:05.560 --> 00:05:06.920 align:middle
el parámetro del bloque,

00:05:07.080 --> 00:05:10.760 align:middle
Puedo mostrar el nombre del mensaje
para ser enviado como un símbolo.

00:05:10.920 --> 00:05:12.480 align:middle
Es incluso más corto.

00:05:12.640 --> 00:05:16.000 align:middle
Solo funciona con mensajes unarios.

00:05:17.920 --> 00:05:20.880 align:middle
Puede usar otros tipos de iteradores.
como "reject:"

00:05:21.040 --> 00:05:24.160 align:middle
Quiero deshacerme de los elementos inpares.
de la colección

00:05:24.320 --> 00:05:27.520 align:middle
En los resultados,
Solo tendré elementos inpares.

00:05:28.520 --> 00:05:30.160 align:middle
O quiero usar "detect:"

00:05:30.320 --> 00:05:34.000 align:middle
Quiero detectar el primer elemento
que coincide con un criterio

00:05:34.160 --> 00:05:37.000 align:middle
el valor del bloque debe ser true.

00:05:37.160 --> 00:05:40.920 align:middle
Quiero el primer elemento inpar
de la colección

00:05:42.320 --> 00:05:46.880 align:middle
A veces, quieres detectar el primero
elemento que coincide con un criterio

00:05:47.040 --> 00:05:50.120 align:middle
Si no hay ninguno,
desea un valor predeterminado:

00:05:50.280 --> 00:05:52.440 align:middle
"detect: ifNone:"

00:05:52.600 --> 00:05:57.360 align:middle
Si no hay coincidencia,
devolverá el valor de este bloque,

00:05:57.520 --> 00:05:59.640 align:middle
que es 0

00:05:59.800 --> 00:06:04.800 align:middle
Hay otros iteradores
que facilitan la vida al programador.

00:06:04.960 --> 00:06:06.800 align:middle
Por ejemplo, "anySatisfy:"

00:06:06.960 --> 00:06:10.600 align:middle
comprueba si un objeto
cumple un criterio

00:06:10.760 --> 00:06:13.320 align:middle
Puede comprobar si todos los objetos
cumple con el criterio

00:06:13.480 --> 00:06:17.320 align:middle
Puede navegar por la colección al revés,
desde el final.

00:06:17.480 --> 00:06:22.360 align:middle
Puede navegar por la colección utilizando un
indice o explorar sus elementos por pares.

00:06:22.520 --> 00:06:26.480 align:middle
Puede navegar por todas las
permutaciones circulares, etc.

00:06:26.640 --> 00:06:28.960 align:middle
Hay muchos iteradores.

00:06:29.120 --> 00:06:31.480 align:middle
También puede crear otras nuevas.

00:06:31.640 --> 00:06:35.320 align:middle
Quiere explorar una colección (1 2 3)

00:06:35.480 --> 00:06:38.440 align:middle
con otra colección (10 20 30).

00:06:38.600 --> 00:06:42.600 align:middle
En el bloque, "do:", tengo
":x" y ":y" que son dos parámetros.

00:06:42.760 --> 00:06:46.840 align:middle
":x" es un elemento
de la primera colección

00:06:47.000 --> 00:06:48.920 align:middle
":y", de la segunda

00:06:49.080 --> 00:06:51.080 align:middle
al multiplicar estos elementos

00:06:51.240 --> 00:06:53.720 align:middle
Los resultados son 10, 40 y 90.

00:06:54.840 --> 00:06:59.440 align:middle
Por supuesto, con este iterador, las dos
colecciones deben ser de igual longitud.

00:07:01.360 --> 00:07:04.720 align:middle
Hay otras formas

00:07:04.880 --> 00:07:08.120 align:middle
aquí utilizo "do: separatedBy:"

00:07:08.280 --> 00:07:11.280 align:middle
Tengo una colección
Examino cada elemento.

00:07:11.440 --> 00:07:14.040 align:middle
Cada vez que se navega un elemento,

00:07:14.200 --> 00:07:17.680 align:middle
Doy valor a un bloque
que coincide con una coma.

00:07:17.840 --> 00:07:20.480 align:middle
Entonces puedo navegar a,

00:07:20.640 --> 00:07:23.320 align:middle
mostrar una
 coma, luego b,
una coma, luego c.

00:07:23.480 --> 00:07:26.400 align:middle
Entre cada elemento,
Realizo una acción.

00:07:28.880 --> 00:07:31.640 align:middle
Este es el iterador "groupedBy:"

00:07:31.800 --> 00:07:36.040 align:middle
Puedo usarlo para agrupar
los elementos de una colección

00:07:36.200 --> 00:07:37.720 align:middle
en función de un criterio.

00:07:37.880 --> 00:07:42.040 align:middle
Envié este mensaje
a la colección 1 2 3 4 5 6 7.

00:07:42.200 --> 00:07:45.480 align:middle
Como resultado, obtengo un diccionario:

00:07:47.000 --> 00:07:50.440 align:middle
todos los elementos que devolvieron false
a este criterio,

00:07:50.600 --> 00:07:52.800 align:middle
que fue #even, los elementos pares.

00:07:52.960 --> 00:07:56.000 align:middle
Como puede ver,
Tengo todos los elementos inpares.

00:07:56.160 --> 00:07:59.520 align:middle
Todos los elementos pares devueltos son true.

00:08:02.280 --> 00:08:04.520 align:middle
A menudo es el caso, cuando computa,

00:08:04.680 --> 00:08:07.720 align:middle
que tiende a anidar colecciones
en colecciones

00:08:07.880 --> 00:08:11.440 align:middle
Termina con grandes niveles de anidación.

00:08:11.600 --> 00:08:14.480 align:middle
Este es un ejemplo creado a mano.

00:08:14.640 --> 00:08:17.560 align:middle
Estas son colecciones
anidadadas en colecciones.

00:08:17.720 --> 00:08:22.200 align:middle
Nos gustaría aplanar la colección
para igualarlo todo.

00:08:22.880 --> 00:08:26.960 align:middle
En Pharo, hay una manera fácil

00:08:27.120 --> 00:08:29.120 align:middle
el iterador "flatCollect:"

00:08:29.280 --> 00:08:33.520 align:middle
Examino los elementos y creo una nueva
colección donde todo es plano.

00:08:35.240 --> 00:08:38.280 align:middle
Entrega
la colección 1 2 3 4 5 6.

00:08:38.440 --> 00:08:40.600 align:middle
Los niveles de anidamiento han desaparecido.

00:08:44.040 --> 00:08:48.520 align:middle
No tengo la intención de presentarle
cada iterador de Pharo.

00:08:48.680 --> 00:08:52.480 align:middle
Sería largo y desagradable.
Solo quiero mostrar que hay muchos.

00:08:52.640 --> 00:08:54.280 align:middle
Puede definir su propio.

00:08:54.440 --> 00:08:57.760 align:middle
Al leer los métodos en la clase Collection

00:08:57.920 --> 00:08:59.560 align:middle
averigua sobre ellos.

00:08:59.720 --> 00:09:02.960 align:middle
Por ejemplo, empiece
por los iteradores que ya conoce.

00:09:03.120 --> 00:09:05.840 align:middle
Puedo preguntarme cómo se implementa "do:"

00:09:06.000 --> 00:09:08.600 align:middle
Lo busco
en la jerarquía de colecciones.

00:09:08.760 --> 00:09:13.760 align:middle
Me doy cuenta de que está implementado
como SequenceableCollection.

00:09:13.920 --> 00:09:16.680 align:middle
El método "do:"
selecciona aBlock como su parámetro.

00:09:16.840 --> 00:09:19.400 align:middle
Esta es la implementación de la colección.

00:09:19.560 --> 00:09:23.320 align:middle
1 to: self size do: [i:|aBlock value: (self at: i)].

00:09:23.480 --> 00:09:26.600 align:middle
Evalúo el bloqueo
utilizado como parámetro

00:09:26.760 --> 00:09:29.840 align:middle
pasándole el elemento en el indice i.

00:09:30.000 --> 00:09:31.160 align:middle
Es muy fácil.

00:09:31.960 --> 00:09:37.280 align:middle
En Pharo, los iteradores son muy poderosos,
como acabamos de ver

00:09:37.440 --> 00:09:41.880 align:middle
Cada colección
apoya los iteradores polimórficamente.

00:09:42.040 --> 00:09:45.200 align:middle
Los programadores usan iteradores

00:09:45.360 --> 00:09:48.240 align:middle
que se implementan
en clases de Collection

00:09:49.000 --> 00:09:51.720 align:middle
de acuerdo con la colección
ellos representan.

00:09:52.520 --> 00:09:55.200 align:middle
Puede definir otros nuevos.
Es muy interesante.

00:09:55.360 --> 00:09:58.840 align:middle
Puedo definir mis propios iteradores
en las clases de Collection

00:10:00.480 --> 00:10:04.480 align:middle
Hay un pequeño matiz
quiénes conocen el patrón de diseño del iterador

00:10:05.160 --> 00:10:10.480 align:middle
un desarrollador no puede elegir
cuándo pasa al elemento siguiente.

00:10:10.640 --> 00:10:14.120 align:middle
La colección lo decide internamente.

00:10:14.280 --> 00:10:17.160 align:middle
no se envía explícitamente el mensaje next
al iterador

00:10:17.320 --> 00:10:20.920 align:middle
Es un matiz para aquellos
que conocen el patrón de diseño del iterador.

00:10:21.520 --> 00:10:25.720 align:middle
Los iteradores son muy poderosos.

00:10:25.880 --> 00:10:28.960 align:middle
Son los mejores amigos del programador.

00:10:29.120 --> 00:10:31.120 align:middle
Facilitan la escritura de programas

00:10:31.280 --> 00:10:34.280 align:middle
Puede escribir código breve, simple,
y elegante.

00:10:34.440 --> 00:10:37.320 align:middle
Se asegura

00:10:37.960 --> 00:10:40.720 align:middle
la encapsulación de datos en una colección.

