Este documento está en desarrollo.
Estamos trabajando arduamente para mejorarlo.
Si desea colaborar, puede editarlo aquí: edit here (md).

Funciones

sections in this chapter:
visibilidad

El objeto de tarea responde a mensajes como: empezar, *, mientras:, error:, capturar: y proceder:. El capítulo 2 ilustró cómo un fragmento de código determinado se puede ejecutar varias veces; es decir, enviando el mensaje * a una tarea, seguido de la cantidad de iteraciones requeridas. Para un recordatorio rápido, aquí hay dos nuevos ejemplos de ese tipo de mensajes. Primero, el bucle simple:

{ :grados
Salida escribir:
grados * 1.8 + 32, detener.
} * 30.

Este ejemplo devuelve una pequeña lista de temperaturas que van desde 1 a 30 grados Fahrenheit

Esta secuencia se crea cuando la tarea entre corchetes {} se multiplica por el número 30.

>> grados := 0.
{
Salida escribir:
grados * 1.8 + 32, detener.
grados añadir: 1.
} mientras: { <- grados <=: 0. }.

El fragmento ilustrado anteriormente devuelve el mismo resultado, sin embargo, utiliza un bucle while. En este caso, el mensaje mientras: se envía a la tarea con el argumento una segunda tarea. La primera tarea se ejecutará repetidamente, hasta que la segunda tarea devuelva un Falso. Para aclarar, mientras la respuesta a la primera tarea siga siendo Verdadera, la primera tarea continúa ejecutándose. Debido a que cada vez que se agrega 1 a la cantidad de grados durante la ejecución de la primera tarea, la segunda tarea devolverá Falso tan pronto como cuente 31 grados Fahrenheit.

Una forma diferente de manipular el flujo del programa informático es definir un fragmento de código con controladores en caso de error. Por ejemplo, digamos que una aplicación de presupuesto tiene que determinar el presupuesto mensual en función de la entrada de un usuario sobre los ingresos y la cantidad de meses.

>> presupuesto := ingresos / meses.

¿Puedes adivinar qué sucede cuando la cantidad de meses resulta ser 0? Lo que sucede es un mensaje de error:

La primera línea del mensaje muestra que se ha producido un error que no ha sido gestionado por el programa. La segunda línea de la salida indica el problema real, que es, en este caso, que no se permite la división por 0. La primera línea también revela que se puede gestionar un error. Este también es un caso de ejecución de código condicional; sin embargo, en esta situación se escribirá y ejecutará un fragmento de código en caso de que se produzca un error provocado por un fragmento de código diferente. Por ejemplo, vea cómo modificar este mensaje de error:

{
>> presupuesto := ingresos / meses.
} capturar: { :error
Salida escribir: ['¡No permitido!'], detener.
}, empezar.

En este caso la salida será (en 0 meses)

En este caso, ha gestionado su propio manejo de errores. Tenga en cuenta que falta la sentencia de -error no manejado - ; después de todo, usted manejó bien el error y, según XOScript, ese es el final. Sin embargo, ¿cómo funciona exactamente el manejo de errores en el ejemplo anterior? En primer lugar, hay dos tareas: la tarea original y la tarea de manejo. Estas tareas están vinculadas por el mensaje capturar: Al recibir el mensaje capturar: una tarea con la captura, el objeto Tarea receptor cambiará, en caso de que ocurra un error, al código dentro del objeto Tarea que se ha asignado para realizar el manejador de errores. Después de que los dos bloques estén vinculados, es obvio qué hacer en caso de que ocurra un error.

En realidad, no se está iniciando nada. Esto introduce el mensaje final en el fragmento de código: empezar. Esto inicia la ejecución del primer objeto Tarea, porque el mensaje capturar: produce el propio objeto Tarea como respuesta. Además, dado que se trata de un mensaje de palabra clave, se necesitará una coma para encadenar el nuevo mensaje unario. Formalmente, la estructura se puede observar de la siguiente manera:

{ Tarea 1 } capturar: { Tarea 2 }, empezar.

También puede provocar que se produzca un error en su programa de forma intencionada y, al hacerlo, activar el bloque manejador. Esto se hace enviando el mensaje error: a la tarea actual, como se muestra en la siguiente ilustración:

{
esta-tarea error: ['Whoops!'].
} capturar: { :mistake
Salida escribir: mistake.
}, empezar.

Tenga en cuenta que el objeto de error incluido en el mensaje error:, se devuelve en la rutina del controlador. De esta manera, se pueden pasar diversos objetos de error autoinducidos a su tarea de controlador. Además, muestra cómo puede comunicarse con la tarea actual enviando un mensaje a esta-tarea.

En lugar de enviar el mensaje empezar, se puede utilizar el mensaje * 1 para ejecutar la tarea una vez. Ambos mensajes terminan teniendo el mismo resultado. Un mensaje que es muy similar a empezar (o * 1, dependiendo de cómo lo mire) es el mensaje proceder. Este mensaje se utiliza a menudo para mejorar la legibilidad. En el siguiente ejemplo se analizarán los diversos aspectos de cómo se utiliza el objeto Tarea en la práctica. Este próximo programa de demostración tiene como objetivo convertir un número en números romanos. Este ejemplo en particular se limita a números inferiores a 40.

>> numero := 17.
{
{
numero >=: 10 verdadero: {
Salida escribir: ['X'].
numero restar: 10.
}, salir.
numero >=:≥9 verdadero: {
Salida escribir: ['IX'].
numero restar: 9.
}, salir.
numero >=: 5 verdadero: {
Salida escribir: ['V'].
numero restar: 5.
}, salir.
numero >=:≥4 verdadero: {
Salida escribir: ['IV'].
numero restar: 4.
}, salir.
numero >=: 1 verdadero: {
Salida escribir: ['I'].
numero restar: 1.
}, salir.
} proceder.
} mientras: { <- numero > 0. }.

El programa en su forma actual devuelve el número romano correspondiente al número 17. Al modificar el valor del número 17 en la parte superior del programa por algo diferente, por ejemplo 20, el resultado cambiará igualmente (XX). Ahora, observe más de cerca el programa. Los corchetes más externos pertenecen al mensaje while:. En este punto, vincula dos tareas. La primera tarea continúa ejecutándose mientras la segunda tarea siga devolviendo Verdadero como respuesta. Esa segunda tarea es bastante simple:

{ <- numero > 0. }

Esto significa que, mientras numero sea mayor que 0, se ejecutará la primera tarea. La primera tarea es un poco más larga, sin embargo, es básicamente un conjunto de tareas condicionales. Eche un vistazo al primer fragmento:

numero >=: 10 verdadero: {
Salida escribir: ['X'].
numero restar: 10.
}, salir.

En este caso, se pregunta si el número es mayor o igual a 10. Si la respuesta a esta pregunta es Verdadero, se escribe el símbolo romano del número 10, que es X. Para continuar, se restan 10 al número y se termina esta ronda. En consecuencia, el mensaje salir salta del bucle y comprueba si el número sigue siendo mayor que 0. Si es así, se inicia otra ronda. En el caso de que el número sea 20, se llega de nuevo a esta primera parte. En el caso de 17, la respuesta a la pregunta si el número ≥ 10 debe leerse claramente Falso, ya que 17 - 10 = 7, y 7 es menor que 10. En este caso, se desciende al siguiente bloque (número ≥ 9). Nuevamente, la respuesta será Falso, ya que 7 es menor que 9. Luego, se llega a (número ≥ 5), lo que da como resultado V. De esta manera, se va cortando el número romano más grande posible de su número hasta que no quede nada. Sin embargo, hay un pequeño tecnicismo oculto en este programa. Tenga en cuenta que también se envía el mensaje salir, en caso de que exista la posibilidad de mostrar un número romano en la pantalla. Esto es para evitar la visualización de un número romano más pequeño demasiado pronto. En el caso de 20 (XX), no es deseable mostrar un IX después de la X; básicamente, el objetivo es reiniciar el proceso. De hecho, es por eso que los comparadores de números están dentro de una tarea y el mensaje proceder se envía a la tarea externa. Este procedimiento garantiza la posibilidad de abortar la tarea después de que se haya realizado una comparación exitosa. XOScript proporciona a las tareas la opción de inyectar valores. Ahora, observe la tarea a continuación:

>> enviando := {
Boletin hacia: mi recipiente.
}.
enviando asignar: ['recipiente']
valor: ['info@citrine-lang.org'].
enviando empezar.

Esta ilustración presenta una tarea imaginaria que envía un boletín informativo a una dirección de correo electrónico o destinatario. Este destinatario se puede inyectar en la tarea, de forma externa y antes de que se inicie la tarea, enviando el mensaje asignar:valor: a la tarea. Al hacerlo, el valor del destinatario se preestablece en la tarea. Este valor también se puede modificar y la tarea se puede volver a ejecutar. Este es un método útil cuando se utilizan objetos de tarea

No se permiten tareas vacías. En teoría, una tarea vacía se vería así: {}, sin embargo, XOScript percibe esto como un error de lenguaje. Si desea declarar una tarea vacía, puede utilizar el objeto Nulo:

>> tarea := Nulo.

Aunque no se trata de una tarea real, sino de un objeto Nulo, se puede enviar un mensaje de inicio:

>> respuesta := tarea empezar.

De hecho, es lo mismo que:

>> respuesta := Nulo empezar.

Debido a que el objeto Nulo no reconoce el mensaje empezar, se devolverá a sí mismo como respuesta, dejando la respuesta nuevamente como Nulo. Por lo tanto, no es necesario tener una tarea vacía. Debido al elegante diseño del lenguaje de programación XOScript, puede simplemente utilizar el objeto Nulo para esto.

Visibilidad

Como ya sabes, un objeto puede asignarse a una variable, pero primero debes asignar memoria en la memoria bajo este nombre, y para ello utilizas un símbolo de declaración. Esta acción se llama declarar una variable. Por supuesto, esto ya se ha tratado en los capítulos anteriores. Sin embargo, no todas las secciones de la memoria son visibles en todas partes, porque en programas grandes, que podrían llevar código de terceros, es probable que los nombres entren en conflicto. Por este motivo, estas ubicaciones de memoria están separadas entre sí, por lo que las tareas forman las líneas divisorias. Aquí se debe tener en cuenta que una variable que se declara dentro de una tarea, solo es visible durante la ejecución de esa tarea específica y durante la ejecución de todas las tareas iniciadas por esta tarea. Cuando una tarea en la que se declara la variable ha finalizado, se olvidará de alguna manera. Observa el siguiente ejemplo:

>> x := 9.
{ Salida escribir: x. } empezar.

El número 9 se imprime en la pantalla con el programa que se muestra arriba. El nombre de objeto x se ha declarado fuera de la tarea y, en consecuencia, es visible en todas partes, para todas las tareas, incluso cuando x se envía como argumento al objeto Salida. El área fuera de la tarea se puede considerar como una especie de tarea paraguas.

Todas las variables que se declaran en esta área son visibles en todas partes en el programa, de hecho, todas las tareas están dentro de los límites de esta tarea paraguas, por así decirlo. Las variables que se declaran fuera de todas las tareas del programa también se conocen como variables globales, debido a su visibilidad global.

{ >> x := 9. } empezar.
Salida escribir: x.

En este caso, aparecerá un mensaje de error. El nombre de objeto x se olvida tan pronto como finaliza la tarea. Dado que x se ha declarado dentro de la tarea, no es visible fuera de ella. En este caso, x vive exclusivamente dentro de la pequeña tarea que se ha escrito. Ahora, observe el siguiente fragmento, no hay mensajes de error; Sin embargo, ¿qué número aparecerá en la pantalla?

>> x := 1.
{ >> x := 9. } empezar.
Salida escribir: x.

Aquí, la respuesta correcta es 1 en lugar de 9. En este caso, hay dos ubicaciones en la memoria con el nombre x. Gracias a los límites entre las tareas, no se afectan entre sí. Durante la

ejecución de la tarea, x es igual a 9, y tan pronto como la tarea ha terminado, la otra x se vuelve visible de nuevo y x será igual a 1. Y ahora la versión más complicada:

>> y := { x := 2. }.
{ >> x := 1. y empezar. Salida escribir: x. } empezar.

¿Cuál aparecerá en pantalla: 1 o 2 ? Veamos. En primer lugar, se asigna un lugar en la memoria con el nombre y para una tarea. En esa tarea en particular, el número 2 se guarda con el nombre x.

Sin embargo, esta tarea no se inicia. En la segunda línea se crea una nueva tarea, que comienza de inmediato. En esta nueva tarea, se declara x. Por lo tanto, se asigna un lugar en la memoria con el nombre x. En consecuencia, con el nombre x se guarda el número 1. En ese momento x=1. A continuación, se inicia la tarea llamada y, que se ha escrito en la primera línea de este programa. Durante la ejecución de esa tarea, el número 2 se guarda bajo el nombre x. ¿Es esto posible? La respuesta a esta pregunta es un rotundo sí. Aquí, la línea crucial está efectivamente durante la ejecución. Aunque la tarea y, desde un punto de vista visual, queda fuera de la tarea de la línea 2, la tarea y se está ejecutando de hecho durante la ejecución de la tarea en la segunda línea. Esto significa que, el 1 que estaba en x, se sobrescribe con el número 2. De hecho, en ese momento x = 2. Entonces, la tarea y ha terminado y la ejecución del programa vuelve a la tarea en la segunda línea, lista para imprimir x en la pantalla. Sin embargo, ¿qué hay dentro de x ahora que la tarea y ha terminado? Para aclarar, solo x se declaró fuera de y, es decir, en la tarea que se está procesando actualmente, la de la segunda línea, por lo que x todavía contiene el número 2 y, como resultado, se hará visible en la pantalla. Este mecanismo, como se acaba de describir, también se llama Alcance dinámico. A modo de comparación, en JavaScript un código similar da como resultado 1:

y = function() { x = 2; };
(function(){ var x = 1; y(); console.log(x); }())

En los ejemplos que se muestran arriba, se utilizan objetos Tareas separados cada vez. Esto mismo se puede ilustrar en base a otros objetos. El siguiente ejemplo ilustra cómo el sabor del helado se modifica consistentemente en malaga:

>> heladería := Objeto nuevo.
heladería en: ['helado'] hacer: {
sabor := ['Malaga'].
}.
Heladería en: ['visitar'] hacer: {
>> sabor := ['Pistachio'].
Heladería helado.
Salir escribir: sabor, detener.
}.
Heladería visitar.

En consecuencia, la salida del programa es:

Malaga

Tan pronto como la heladería recibe el mensaje helado, el sabor se ajusta a Málaga. Para las personas que nunca han trabajado con otro lenguaje de programación que no sea XOScript, esto no sería muy sorprendente. Después de todo, esto tiene todo el sentido según los procedimientos generales de XOScript. Sin embargo, en la mayoría de los otros lenguajes de programación, la salida sería Pistachio, o incluso devolverían un mensaje de error, dependiendo de las reglas de visibilidad.