Manual de Basic Spectrum 48k.

Capítulo 9

Funciones

Resumen

  • FN
  • LEN, STR$, VAL, SGN, ABS, INT, SQR
  • FN

Considere una máquina de hacer embutidos. Suponga que pone un trozo grande de carne en un extremo, gira una manivela y obtiene a la salida en el otro extremo, un embutido de carne. Un hecho analogo se tendría con cualquier otro ingrediente destinado a la fabricación de embutido.

Las funciones son algo similar a estas máquinas de embutidos pero hay una diferencia: trabajan con números y cadenas de caracteres en lugar de hacerlo con carne. Suministre un valor (llamado el argumento), trátelo efectuando algunos cálculos y, finalmente, obtendrá otro valor, el resultado.

Entrada de carne --> Máquina de embutidos --> Salida de embutidos
Entrada argumento --> Función --> Salida resultado

Argumentos diferentes proporcionan resultados diferentes y si el argumento es completamente incorrecto, la función se interrumpirá y dará un informe de error.

Los mismo que puede tener máquinas diferentes para obtener productos diferentes, funciones distintas realizarán cálculos distintos. Cada una tendrá su propio valor para distinguirla de las demás.

En las expresiones, una función se utiliza escribiendo su nombre seguido del argumento y cuando la expresión es evaluada, se obtiene el resultado de la función.

Como ejemplo una función denominada LEN, que da como resultado la longitud de una cadena de caracteres. Su argumento es la cadena cuya longitud queremos determinar y su resultado es la longitud, de modo que si teclea:

PRINT LEN "Sinclair"

el ordenador escribirá la respuesta 8, que es el número de letras existentes en la palabra "Sinclair". (Para obtener LEN, como en el caso de la mayoría de los nombres de funciones, debe utilizar el modo extendido, esto es: pulse CAPS SHIFT y SYMBOL SHIFT, al mismo tiempo, para cambiar el cursor de  L  a  E  y luego, pulse la tecla L

Si mezcla funciones y operaciones en una sola expresión, entonces las funciones tendrán prioridad sobre las operaciones. Sin embargo, también en este caso, puede eludir esta regla utilizando paréntesis. Por ejemplo, damos a continuación dos expresiones que sólo difieren en los paréntesis y, sin embargo, los cálculos se realizan en un orden completamente distinto en cada caso (aunque, como por casualidad, los resultados finales son los mismos).

LEN "Fred" + LEN "Bloggs" LEN ("Fred" + "Bloggs")
4 + LEN "Bloggs" LEN ("FredBloggs")
4 + 6 LEN "FredBloggs"
10 10

Veamos, ahora, algunas otras funciones.

STR$ convierte números en cadenas: su argumento es un número y su resultado es la cadena que aparecía enla pantalla si el número se visualizara por medio de una sentencia PRINT. Observe cómo su nombre finaliza en un signo $ para indicar que su resultado es una cadena. Por ejemplo, podría decir:

LET a$ = STR$1e2

que tendría exactamente el mismo efecto que si se tecleara:

LET a$ = "100"

O también podría escribir:

PRINT LEN STR$ 100.0000

y obtener la respuesta 3, porque STR 100.0000 = "100".

VAL es similar a STR$ en el sentido inverso: convierte cadenas en números. Por ejemplo:

VAL "3.5" = 3.5

En un sentido, VAL es la inversa de STR$, porque si toma cualquier número, le aplica STR$ y luego, le aplica VAL, volverá a obtener el número original.

VAL es una función muy potente, porque la cadena en la que está su argumento no está restringida a que sea como un número sencillo, sino que puede ser cualquier expresión numérica. Así, por ejemplo:

VAL "2*3" = 6

o también:

VAL ("2" + "*3") = 6

Hay dos procesos actuando en este caso. En el primero, el argumento de VAL se evalúa como una cadena: la expresión de cadena "2" + "*3" se evalúa para obtener la cadena "2*3". Entonces, se eliminan las comillas de la cadena y lo que queda se evalúa como un número: así pues, 2*3 una vez evaluado dará el número 6.

Esto puede ser extremadamente confuso si no conserva su "presencia de ánimo"; por ejemplo:

PRINT VAL "VAL""VAL""""2"""""""

(Recuerde que en el interior de una cadena unas comillas de cadena deben escribirse dos veces. Si profundiza más en las cadenas, encontrará que las comillas de cadena necesitan cuadruplicarse o incluso octuplicarse).

Hay otra función, bastante similar a VAL, aunque probablemente menos útil, denominada VAL$. Su argumento sigue siendo una cadena, pero su resultado es también una cadena. Para ver como actua, recuerde que VAL tiene una acción en dos pasos: primero, su argumento se evalúa como un número. Con VAL$, el primer paso es el mismo, pero después de eliminarse las comillas de cadena en el segundo paso, lo que queda se evalúa como otra cadena. Así:

VAL$ """Chocolate""" = "Chocolate"

(Observe cómo las comillas de cadena proliferan de nuevo).

Haga:

LET a$ = "99"

e imprima todo lo siguiente: VAL a$, VAL "a$", VAL """a$""", VAL$ a$, VAL "a$" y VAL$ """a$"""$""". Algunas de ellas actuarán y otras no lo harán; intente encontrar explicación a todas las respuestas.

SGN es la función signo. Es la primera función que ha visto que no tiene nada que hacer con las cadenas, porque su argumento y su resultado son números. El resultado es +1 si el argumento es positivo, 0 si el argumento es cero y -1 si el argumento es negativo.

ABS es otra función cuyo argumento y cuyo resultado son números. Convierte el argumento en un número positivo (que es el resultado) haciendo caso omiso del signo, de modo que por ejemplo:

ABS -3.2 = ABS 3.2 = 3.2

INT significa "parte entera" (un entero es un número entero, que puede ser negativo). Esta función convierte un número fraccionario, con cifras decimales, en un entero suprimiendo la parte fraccionaria, así por ejemplo:

INT 3.9 = 3

Ha de tener cuidado al aplicar esta función a números negativos, porque siempre hay que redondear por defecto; así, por ejemplo:

INT -3.9 = -4

SQR calcula la raíz cuadrada de un número y el resultado multiplicado por si mismo, da el argumento. Por ejemplo:

SQR 4 = 2 porque 2*2 = 4
SQR 0.25 = 0.5 porque 0.5 * 0.5 = 0.25
SQR 2 = 1.4142136 (aproximadamente) porque 1.4142136 * 1.4142136 = 2.0000001

Si multiplica cualquier número (incluso uno negativo) por si mismo, la respuesta es siempre positiva. Ello significa que los números negativos no tienen raices cuadradas, por lo que si aplica SQR a un argumento negativo obtendrá un informe de error An Invalid Argument (un argumento no válido).

Asimismo, puede definir funciones por su cuenta. Posibles nombres para estas funciones son FN seguido por una letra (si el resultado es un número) o FN seguida por una letra y por $ (si el resultado es una cadena). Hay más rigurosidad con respecto a los paréntesis: el argumento debe encerrarse entre paréntesis.

Defina una función poniendo una sentencia DEF en algún lugar del programa. Por ejemplo, veamos la definición de una función FN s, cuyo resultado sea el cuadrado del argumento:

10 DEF FN s(x) = x * x: REM el cuadrado de x

DEF se obtiene en modo extendido, con el empleo de SYMBOL SHIFT y de 1. Cuando haya escrito esto, el ordenador le dará automáticamente FN porque en una sentencia DEF, FN siempre va inmediatamente detrás de DEF. A continuación, la letra s completa el nombre de FN s de la función.

La x entre paréntesis es un nombre mediante el cual desea referirse al argumento de la función. Puede utilizar cualquier letra única que quiera para ello (o, si el argumento es una cadena, una sola letra seguida por el $).

Después del signo = está la definición real de la función. Esta puede ser cualquier expresión y puede referirse también al argumento utilizando el nombre que le ha dado (en este caso, x) como si fuera una variable ordinaria.

Una vez introducida esta línea, puede invocar, o llamar, la función como si se tratara de las propias funciones del ordenador, tecleando su nombre, FN s, seguido por el argumento. Recuerde que una función definida por usted, debe llevar el argumento encerrado entre paréntesis. Pruébelo unas cuantas veces:

PRINT FN s(2)
PRINT FN s(3 + 4)
PRINT 1 + INT FN s(LEN "pollo" / 2 + 3)

Una vez que haya puesto la sentencia DEF correspondiente en el programa, puede utilizar sus propias funciones en expresiones con la misma libertad que puede emplear las del ordenador.

Nota: En algunas versiones de BASIC, debe encerrar entre paréntesis el argumento de una de las funciones del ordenador. Este no es el caso en el BASIC del ZX Spectrum.

INT siempre redondea por defecto. Para redondear al entero más próximo, añada primero 0.5 (podría escribir su propia función para hacer esta operación).

20 DEF FN r(x) = INT (x + 0.5): REM da x redondeada al entero más próximo.

Entonces, obtendrá, por ejemplo:

FN r(2.9) = 3 FN r(2.4) = 2
FN r(-2.9) = -3 FN r(-2.4) = -2

Compare estas respuestas con las que consigue cuando utiliza INT en lugar de FN r. Escriba y ejecute lo siguiente:

10 LET x = 0: LET y = 0: LET a = 10
20 DEF FN p(x,y) = a + x * y
30 DEF FN q() = a + x * y
40 PRINT FN p(2,3), FN q()

Hay muchos puntos sutiles en este programa.

Primero, una función no está restringida a un solo argumento: puede tener más o incluso ninguno en absoluto, pero siempre debe mantener los paréntesis.

Segundo, no importa en qué lugar del programa ponga las sentencias DEF. Una vez que el ordenador haya ejecutado la línea 10, simplemente salta por encima de las líneas 20 y 30 para llegar a la línea 40. Sin embargo, han de estar en cualquier lugar del programa y no pueden estar en un comando.

Tercero, x e y son los nombres de variables en el programa como un conjunto, y los nombres de argumentos para la función FN p. FN p olvida temporalmente las variables denominadas x e y, pero puesto que no tiene ningún argumento denominado a, todavía recuerda la variable a. Por consiguiente, cuando se está evaluando FN p(2,3), a tiene el valor 10 porque es la variable, x tiene el valor 2 porque es el primer argumento e y tiene el valor 3 porque es el segundo argumento. El resultado es, entonces: 10 + 2 * 3 = 16. Cuando se está evaluando FN q(), por el contrario, no hay ningún argumento, por lo que a, x e y se refieren todavía a las variables y tienen los valores 10, 0 y 0 respectivamente. La respuesta, en este caso, es: 10 + 0 * 0 = 10.

Ahora cambie la línea 20 a:

20 DEF FN p(x,y) = FN q()

Esta vez, FN p(2,3) tendrá el valor 10 porque FN q volverá también a las variables x e y en lugar de emplear los argumentos de FN q.

Algunas versiones del BASIC (y no precisamente la del BASIC del ZX Spectrum) tienen funciones denominadas LEFT$, RIGHT$, MID$ y TL$.

LEFT$ (a$,n) da la subcadena de a$ que consta de los primeros n caracteres.

RIGHT$ (a$,n) da la subcadena de a$ que está constituida por n2 caracteres que comienzan en el n1-ésimo.

MID$ (a$, n1, n2) da la subcadena de a$ que está constituida por n2 caracteres que comienzan en el n1-ésimo.

TL$ (a$) da la subcadena de a$ que está constituida por todos sus caracteres con la excepción del primero.

Puede escribir algunas funciones definidas por el usuario para hacer lo mismo, por ejemplo:

10 DEF FN t$(a$) = a$(2 TO): REM TL$
20 DEF FN i$(a$,n) = a$(TO n): REM LEFT$

Compruebe que estas actúan con cadenas de longitud 0 y 1.

Observe que nuestra función FN i$ tiene dos argumentos, uno es un número y el otro es una cadena. Una función puede tener hasta 26 argumentos numéricos (¿por qué precisamente 26?) y, al mismo tiempo, hasta 26 argumentos de cadena.

Ejercicio

Utilice la función FN s(x) = x * x para probar SQR; debe encontrar que

FN s(SQR x) = x

si sustituye x por cualquier número positivo y

SQR FN s(x) = ABS x

si x es un número positivo o negativo (¿por qué ABS?).


Manual de Basic Spectrum 48k.