Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Referencia rápida de Smalltalk

Ejemplos de sintaxis Smalltalk

nota: para ver los resultados de cada fragmento de código, selecccionarlo y usar la opción print-it (ctrl+p) para ver el resultado en el mismo editor de código, o la opción inspect-it (ctrl+i) para abrir un inspector sobre el resultado

Elementos generales del lenguaje

"Comentarios van entre comillas dobles,
y pueden tener varias líneas"

. "el punto sirve para separar colaboraciones"

^ objeto "sirve para retornar un objeto dentro de un método"

a := objeto "sirve para establecer una referencia al objeto a través del nombre 'a' (asignación)"

Expresiones básicas

Tipos de mensaje

mensajes unarios

3 factorial.  "objeto receptor 3 (número entero); mensaje #factorial"
2 even.       "objeto receptor 2 (número entero); mensaje #even (es par)"
'hola' size.  "objeto receptor 'hola' (string);   mensaje #size (tamaño)"

mensajes binarios

(tambien llamados aritméticos)

3 + 4.              "objeto receptor 3;        mensaje + 4 (nombre de mensaje #+; colaborador externo 4)"
'hola', ' mundo'    "objeto receptor 'hola';   mensaje , ' mundo' (nombre de mensaje #; colaborador externo ' mundo')"
true & false        "objeto receptor true;     mensaje & false (nombre de mensaje #&, colaborador externo false)"

Mensajes de palabra clave (keyword)

"de una palabra clave"
3 raisedTo: 4.        "3 recibe el mensaje #raisedTo: con colaborador externo 4"
'hola' at: 2.         "'hola' recibe el mensaje #at: con colaborador externo 2"
true and: [ false ].  "true recibe el mensaje #and: con colaborador externo [ false ]"

"de mas de una palabra clave"
3 between: 1 and: 10. "3 recibe el mensaje #between:and: con colaboradores externos 1 y 10 respectivamente"

Orden de evaluación

Toda expresión Smalltalk se analizará de izquierda a derecha, resolviendo primero los mensajes unarios, luego los binarios y por último los mensajes de palabra clave. Pueden agregarse paréntesis para alterar el orden por defecto, forzando así la evaluación de lo que esté encerrado en los paréntesis.

Ejemplo:

3 factorial + 1 between: 'ay' size and: (3 raisedTo: 1) + 2 * 3. "paso inicial"
6 + 1 between: 'ay' size and: (3 raisedTo: 1) + 2 * 3.           "resuelve 3 factorial (siguiente en prioridad desde izq.)"
7 between: 'ay' size and: (3 raisedTo: 1) + 2 * 3.               "resuelve 6 + 1 (siguiente en prioridad izq.)"
7 between: 2 and: (3 raisedTo: 1) + 2 * 3.                       "resuelve 'ay' size (siguiente en prioridad izq.)"
7 between: 2 and: 3 + 2 * 3.                                     "resuelve el paréntesis, toma precedencia"
7 between: 2 and: 5 * 3.                                         "resuelve 3 + 2 (siguiente en prioridad izq.)"
7 between: 2 and: 15.                                            "resuelve 5 * 3 (siguiente en prioridad izq.)"
true.                                                            "resuelve el ultimo mensaje de palabra clave"

Este mismo ejemplo se puede visualizar de una manera interactiva usando el debugger. En un workspace, pegar la expresión y evaluarla usando debug-it (ctrl+shift+d). Luego, dentro del debugger usar la opción Over para ir viendo qué mensajes se van enviando.

Objetos globalmente conocidos

Booleanos

true.  "no confundir con True, que es la clase que representa el valor de verdad verdadero"
false. "no confundir con False, que es la clase que representa el valor de verdad falso"

Objeto nulo

nil.   "representa la noción de no-objeto, y es la única instancia de la clase UndefinedObject"

Números

3.          "número entero"
5.12.       "número racional, instancia de Float"
3 / 4.      "número fraccionario, instancia de Fraction"
1010r2.     "número en otra base que no sea 10 (en este caso binario, base 2)"
Float pi.   "forma de obtener números conocidos a través de envío de mensajes"

Mensajes útiles:

  • Aritméticos: +, -, *, /
  • Conversión: asFloat, asFraction, asInteger

Strings

'hola'.            "creación con comillas simples"
'hola', ' mundo'.  "concatenación"
'hola' size.       "para saber el tamaño"
'hola' at: 3.      "conocer el n-ésimo elemento"
'hola mundo' copyFrom: 2 to: 8.   "obtener un sub-string"

Para más mensajes, revisar el protocolo público de String y sus superclases (SequenceableCollection y Collection).

Bloques

Un bloque es un objeto, contiene una o múltiples colaboraciones que no se ejecutan hasta que le enviemos el mensaje #value.

[ 3 factorial ].          "nos retorna el bloque tal como está"
[ 3 factorial ] value.    "retorna el resultado de evaluar el bloque"

Los bloques también pueden tener colaboradores externos, en cuyo caso se evalúan con el mensaje #value:, o #value:value: dependiendo de la cantidad de colaboradores externos que tenga.

[ :numero | numero + 3 ] value: 2.
[ :x :y | x raisedTo: y ] value: 2 value: 3.

Dicho de otra forma, un bloque es como un método sin nombre.

Colecciones

Array

Los arreglos (arrays) son instancias de la clase Array y tenemos 3 formas de construirlos:

  • Arreglo de literales: #(1 2 3 'hola') (sólo pueden contener objetos literales, como numeros, strings, caracteres u otros arrays)
  • Arreglos utilizando llaves {}: { 3 factorial . 'hello' size . 8 } (pueden contener cualquier expresión)
  • Construcción sin sintaxis especial: Array with: 1 with: 2 with: 3 (equivalente a la notación de llaves)

Para más mensajes, revisar el protocolo público de Array y sus superclases (ArrayedCollection, SequenceableCollection y Collection).

Set

Instancias de la clase Set representan un conjunto de elementos que no admite repetidos, ni tiene un orden. Agregar un elemento reiteradas veces no genera errores, si no que simplemente

OrderedCollection

Instancias de la clase OrderedCollection representan listas, cuyos elementos se ordenan por orden de llegada, y admite repetidos. Es el caso más común para diferentes dominios.

Bag

Al igual que un Set, no tiene orden, pero la diferencia es que admite repetidos.

SortedCollection

Las SortedCollection son colecciones que mantienen sus elementos ordenados en base a un criterio que le proveemos, y por defecto se utiliza el orden natural (determinado por el mensaje <). En caso de desear otro orden, se le provee un sortBlock, que es un bloque de dos colaboradores externos que representan dos elementos de colección, en el que especificamos el criterio de ordenación.

También podemos convertir una colección a una SortedCollection a través de los mensajes asSortedCollection y asSortedCollection: (esta última variante para especificar el sortBlock).

Ejemplos:

"generar una SortedCollection con 2, 3, y 5 en ese orden"
SortedCollection with: 3 with: 5 with: 2.
"generar una SortedCollection con palabras ordenadas por cantidad de caracteres, de mayor a menor"
SortedCollection sortBlock: [ :palabra1 :palabra2 | palabra1 size > palabra2 size ].
"ordenar una colección de personas por edad, de menor a mayor"
personas asSortedCollection: [ :persona1 :persona2 | persona1 esMasJovenQue: persona2 ].

Caracteres

Los caracteres se crean de manera literal con el símbolo $. Por ejemplo, para crear la letra "a" escribimos $a, para crear el número 1, escribimos $1, y así. Los strings contienen caracteres, por ejemplo, cuando accedemos a un elemento obtenemos un caracter. Ejemplos:

'hola' last.     "esto devuelve un caracter como resultado"
'hola' at: 2.    "esto devuelve un caracter como resultado"
$1 isDigit.      "saber si un caracter es un número"
$a isVowel.      "saber si un caracter es una letra vocal"

Condicionales

Las expresiones condicionales (if-then-else) se escriben enviando mensajes a los booleanos que representan la condición. Ejemplos:

3 > 4 ifTrue: [ 'una locura' ].
'hola' isEmpty ifFalse: [ 'esto tiene sentido' ].
numero even ifTrue: [ 'es par!' ] ifFalse: [ 'es impar! '].

Igualdad e Identidad

En Smalltalk, todos los objetos responden a los mensajes = y ==, para determinar la igualdad y la identidad respectivamente.

Un objeto sólo es idéntico a si mismo, es por ello que expresiones como 1 == 1 o variable == variable dan true, porque nos estamos refiriendo a la misma cosa.

La igualdad, por defecto es similar a la identidad (puede verse la implementación de = en Object), pero puede redefinirse. Por ejemplo, podríamos decir que dos aulas se consideran iguales si su nombre es el mismo:

"Definicion de Aula>>="
= otraAula

  ^ self nombre = otraAula nombre

Clases y métodos abstractos

En Smalltalk, no hay ninguna manera de indicar que una clase es abstracta. Es responsabilidad de quien programa de no utilizarlas, y/o escribir comentarios aclarando que se trata de una clase abstracta (como por ejemplo, Collection).

Sin embargo, podemos definir métodos abstractos. Un método abstracto se define poniendo self subclassResponsibility en la parte de implementación. Ejemplo de Collection>>add::

add: newObject 
	"Include newObject as one of the receiver's elements. Answer newObject. 
	ArrayedCollections cannot respond to this message."

	self subclassResponsibility

Si alguna subclase no redefine este mensaje, en momento de ejecución recibiremos un error indicando que era responsabilidad de la subclase dar una definición para ese mensaje.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment