Paradigmas de Lenguajes de Programación
Smalltalk (Parte II)
1er cuatrimestre de 2007
Anteayer nomás...


Un objeto consta de una representación interna
y un protocolo.
En Smalltalk todo es un objeto.

Por ejemplo el número 10.

La cadena 'hola, soy una cadena'.

El valor booleano true.

El transcript donde se trabaja.

El código del programa que escribo.

O sea... ¿todo es un objeto?

¡Sí! Todo, todo.
Anteayer nomás...

También tenemos variables, las cuales pueden
referenciar objetos.
Por ejemplo:

unaFrase := 'Ser o no ser...'
unaFrase
'Ser o no ser...'
String
Anteayer nomás...

Los objetos interactúan entre sí a través del
envío de mensajes.
Persona

encender
Cafetera
Los mensajes pueden ser unarios, binarios o
keyword.
Todo muy lindo, pero...

¿Cómo hago algo útil con todo esto?

Empecemos por un ejercicio fácil.


Escribir un fragmento de código que evalúa la
variable x y si es igual a cero imprime ‘Cero’ en el
transcript.
Parecería que necesitamos algún tipo de estructura
de control condicional if.
Condicionales en Smalltalk

En los lenguajes de programación imperativos
existen, como parte del lenguaje, estructuras de
control de flujo:
If (condición) {
sentencias
}

¿Pero cómo hacemos esto en Smalltalk donde
todo es un objeto?

¿Ideas?
¿Qué tal esta alternativa?
[codigo] executeIf: condicion

No nos sirve. ¿Por qué?


Porque el objeto que recibe el mensaje no tiene
forma de verificar si el booleano que recibe es
efectivamente true porque necesitaría un if…
Y eso es precisamente lo que estamos intentando
implementar.
¿Qué tal esta otra?
condicion ifTrue: [codigo]

Es lo mismo pero ahora el receptor del mensaje
es el booleano. ¿Cambia algo?


Sí, porque podemos utilizar el polimorfismo que nos
provee este paradigma para desviar el flujo de
control.
¿Y cómo hacemos esto?
Booleanos

La condición es un objeto de la clase Boolean
Boolean
True


False
Tiene subclases True y False, cada una con
una única constante, true y false
respectivamente.
Cada vez que evaluamos una expresión
booleana en Smalltalk el resultado es una de
estas dos constantes.
condicion ifTrue: [sentencias].

¿Cuál es el parámetro?



Un bloque de código, perteneciente a la clase
BlockClosure. (Recordar: ¡Todo es un objeto!)
Los bloques pueden tener parámetros o no:

[Transcript show: ‘Hola’.]

[:x :y | x == 10 + y.]
Se ejecutan enviándoles el mensaje value, que
puede ser unario para el caso de bloques sin
parámetros o keyword con tantos parámetros como
el bloque tiene.
Bloques

Ejecutando (evaluando) bloques:

[Transcript show: ‘Hola’.] value.


[:x :y | x == 10 + y.] value: 21 value: 11.


Devuelve true.
Los bloques pueden tener variables locales:


Imprime la cadena ‘Hola’ en el transcript.
miBloque := [:i | |z| z := i. z := z * z. z + 1.]
Devuelven el resultado de la última sentencia:

miBloque value: 2.
devuelve 5
¿Cómo está implementado el if?

Recordar, Boolean tiene dos subclases.

Clase True, método ifTrue: unBloque

Ejecuto el bloque:


unBloque value.
Clase False, método ifTrue: unBloque

No hago nada.
¿Entoces el ejercicio…?

Escribir un fragmento de código que evalúa la variable
x y si es igual a cero imprime ‘Cero’ en el transcript.
x == 0 ifTrue: [Transcript show: ‘Cero‘.].
Más de boolean





condicion ifFalse: [sentencias]
condicion ifTrue: [sentencias1]
ifFalse: [sentencias2]
booleano1 & booleano2
booleano1 | booleano2
booleano and: [sentencias]


Evalua el bloque y al resultado le aplica and con el booleano.
booleano or: [sentencias]

Evalua el bloque y al resultado le aplica or con el booleano.
Otro ejercicio


Escribir un bloque de código que tome un parámetro y
al ser evaluado (en un entero positivo) imprima en el
transcript todos los números desde el 0 hasta el que
recibió.
Parece que ahora necesitamos algún tipo de
estructura de control que nos permita iterar.
m to: n do: [:actual | sentencias]

La clase Integer acepta un mensaje to:do:

Espera otro entero y un bloque con un parámetro.


Evalúa el bloque usando como parámetro cada entero entre m
y n.
¿Entonces el ejercicio…?
[:limite |
0 to: limite do:
[:actual |
Transcript show: actual displayString ; cr.
].
]
Otras formas de iterar

m to: n by: step do: [:actual | sentencias]


m timesRepeat: [sentencias]


Repite m veces el bloque sentencias.
[condicion] whileTrue: [sentencias]


Igual pero incrementando de a step en cada paso.
Ejecuta sentencias mientras la evaluación de
condicion sea true. ¿Por qué no usar un Boolean?
[condicion] whileFalse: [sentencias]

Análoga a la anterior.
Igualdad

Smalltalk puede verificar dos tipos de
igualdades entre objetos.

Igualdad estricta:


Igualdad semántica (o equivalencia):



a = b es true si a y b son la misma instancia.
a == b es true si a y b son equivalentes según alguna
relación que debe ser implementada para cada clase.
a ~= b sería (a = b) not
a ~~ b sería (a == b) not
Colecciones en Smalltalk

Smalltalk ofrece una amplia variedad de tipos
de colecciones que podemos usar según la
necesidad del caso:




¿Elementos ordenados?
¿Se admiten duplicados?
Etc.
Tener en cuenta que las colecciones son
heterogéneas, siempre se admiten elementos
de tipos diversos.
Colecciones, colecciones, …
Algunas operaciones básicas (I)
• at:
• at:put:
• size
a := #(1 2 3 4) copy.
a at: 1.
a at: 2 put: ‘dos’.
a size
Set
• add:
• size
• includes:
s := Set new.
s add: 1; add: 1; add: 2.
s size.
s includes: 4.
Bag
• add:
• size
• includes:
• occurrencesOf:
b := Bag new.
b add: 1; add: 1; add: 2.
b size.
b includes: 1.
b occurrencesOf: 1.
Array
• at:put:
• at:
• includes: (contiene valor)
Dictionary • includesKey: (contiene clave)
• size
• keys
d := Dictionary new.
d at: 'hola' put: 'hello'.
d at: ‘hola'.
d includesKey: 'loro'.
Algunas operaciones básicas (II)
• includes:
in := Interval from: 3 to: 30 by: 5.
in includes: 4.
in includes: 8.
Ordered
Collection
• add:
• at:
• at:put:
• first
• last
• addFirst:
• addLast:
• removeFirst:
• removeLast:
• indexOf:
oC := OrderedCollection new.
oC add: 3; add: 2; add: 5.
oC add: 4 after: 2.
Sorted
Collection
• add:
• sortBlock:
x := SortedCollection new.
x add: 3; add: 2; add: 5.
x sortBlock: [:a :b | a >= b].
Interval
Operaciones para todas las collections (I)
do: [:actual | sentencias]
Evalúa el bloque en cada uno de los elementos
de la colección.
select: [:actual | sentencias]
El bloque debe retornar un valor booleano. Se
devuelve otra colección (del mismo tipo de la
receptora)
conteniendo
únicamente
los
elementos para los cuales la ejecución del
bloque da true.
reject: [:actual | sentencias]
Análoga a la anterior pero guardando los
elementos que hacen al bloque false.
collect: [:actual | sentencias]
Se devuelve otra colección (del mismo tipo de la
receptora) conteniendo los resultados de la
aplicación del bloque a cada elemento de la
colección receptora.
Operaciones para todas las collections (II)
detect: [:actual | sentencias]
detect: [:actual | sentencias1]
ifNone: [sentencias2]
El bloque debe retornar un valor booleano. Se
devuelve el primer elemento de la colección
que hace al bloque evaluar en true.
En caso de que todos evalúen el bloque en
false se genera un error en tiempo de
ejecución.
Igual a la anterior, pero en caso de no
encontrar ningún elemento que haga al bloque
ser verdadero, se evalúa el segundo bloque y
no se genera un error.
El primer parámetro del bloque es el resultado
parcial de la operación, comenzando por
casoBase. El segundo parámetro es el
inject: casoBase into:
[:resParcial :elemActual | sentencias] elemento actual de la colección receptora.
Se devuelve el resultado de la última
evaluación
Ejercicio de colecciones
Agregarle a la clase Collection un método:
selectAnyTwoOf: bloque1 or: bloque2 or: bloque3
Donde los tres bloques tienen un parámetro y
evaúan a Boolean.
Debe devolver una nueva colección (del mismo
tipo de la receptora) cuyos elementos son
aquellos de la colección original tales que hacen
valer true a exactamente dos de los bloques.
Ejercicio de colecciones: solución
selectAnyTwoOf: bloque1 or: bloque2 or: bloque3
^self select:
[:elem |
|n|
n := 0.
(bloque1 value: elem) ifTrue: [n := n + 1.].
(bloque2 value: elem) ifTrue: [n := n + 1.].
(bloque3 value: elem) ifTrue: [n := n + 1.].
n == 2.
].
Ejercicio de parcial
Agregar en Smalltalk a la clase Collection el siguiente método:
generateBlock: aBlockList
Este método recibe una lista de bloques de un parámetro que evalúan a Boolean.
Se debe devolver un nuevo bloque b de un parámetro que evalúa a Boolean tal
que:
b value:n es verdadero si y sólo si:

b1 value:n es True

b2 value:n es False

b3 value:n es True

b4 value:n es False
… (valores de verdad intercalados)
donde <b1,b2,...,bn> son todos los bloques de aBlockList que son satisfechos por al
menos un elemento de la colección receptora.
Ejercicio parcial: solución
generateBlock: aBlockSecuence
|secuenciaFiltrada alter|
secuenciaFiltrada := aBlockSecuence select:
[:b | (self select: [:e | b value:e] ) size > 0].
alter := false.
^ secuenciaFiltrada inject: [:p | true] into:
[:b :m |
(alter := (alter not)).
alter ifTrue:
[ [:p | (b value: p) & ((m value: p) == true)] ]
ifFalse:
[ [:p | (b value: p) & ((m value: p) == false)] ]
].
¡Eso es todo!
¿?
clase avisar: ‘eso es todo por hoy’
Descargar

Paradigmas de Lenguajes de Programación