lunes, 15 de agosto de 2016

Seguimos con Smalltalk, parte 3


En Smalltalk el comportamiento (el código) también es un objeto.  Los bloques son una forma de capturar comportamiento (código) en un objeto para utilizarlo a nuestra discreción.  La forma básica de un bloque es una lista de expresiones, separadas por un punto, encerradas entre corchetes ([]).

[ExpresiónSmalltalk1].
[ExpresiónSmalltalk1. ExpresiónSmalltalk2].

La forma de activar un bloque (de ejecutar el código que encierra) es enviándole el mensaje #value. La última expresión del bloque será el valor de retorno.

| bloque |
bloque := [World flash]. "En este punto el mundo NO parpadea"
bloque value. "Ahora que evaluamos el bloque el mundo SI parpadea"

Una cosa muy interesante del lenguaje Smalltalk es que no existen, como parte de la sintaxis, las 'estructuras de control'.  La funcionalidad que los lenguajes tradicionales se da con extensiones en la sintaxis, en Smalltalk se resuelve con mensajes a objetos.

Smalltalk allClasses size > 2000
        ifTrue:[Transcript show: '¡Cuantas clases!'; cr].


Smalltalk allClasses size > 2000
        ifTrue:[Transcript show: '¡Cuantas clases!']
        ifFalse:[Transcript show: '¡No son tantas las clases!'].
Transcript cr.

| número paridad |
número := 11.
(número \\ 2) = 0
    ifTrue:[paridad := 0]
    ifFalse:[paridad := 1].

| número paridad |
número := 11.
paridad := (número \\ 2) = 0 ifTrue:[0] ifFalse:[1].

Veamos una estructura tipo WHILE:
| index |
index := 1.
[index < 10]
    whileTrue:[
        Transcript show: index; cr.
        index := index + 1
    ].

Veamos una estructura tipo FOR:
1 to: 10 do:[:index | Transcript show: index; cr].
1 to: 10 by: 2 do:[:index | Transcript show: index; cr].

25 timesRepeat:[Transcript show: '.'].
Transcript cr.

Es muy interesante ver la implementación del los métodos True>>ifTrue:ifFalse: y False>>ifTrue:ifFalse: para entender como funcionan las 'estructuras de control' con objetos y mensajes.

A los bloque, también, se les puede activar con argumentos.  La sintaxis para definir un bloque que necesita argumentos para evaluarse es la siguiente:

[:argumento1 | Expresiones].
[:argumento1 :argumento2 | Expresiones].

Para activar un bloque que requiere un argumento se usa el mensaje #value:, para activar uno que requiere 2 argumentos se usa el mensaje #value:value:, y así sucesivamente para bloques con 3 o más argumentos.

| productos |
productos := #(2 3 5 7 11 13) collect:[:primo | primo * primo].
Transcript show: productos; cr.


| colección |
colección := SortedCollection sortBlock:[:x :y | x size < y size].
colección add: 'un string más largo'.
colección add: 'un string'.
colección add: #(#un #array #con @simbolos).
Transcript show: colección; cr.

Y, por último, se pueden declarar variables temporales al bloque con la siguiente sintaxis.

[| variableTemporal | Expresiones].
[:argumento1 | | variableTemporal | Expresiones].