Consejos de Programación para Scripters

Autor: Yacobs
Email: macmardigan@madrid.com
Fecha: 19/09/2001

---------------
A) Introducción
---------------
Estos consejos van orientados a aquellos que empiezan con el scripting y no han programado nunca antes. El scripting no es un lenguaje de programación y no admite ciertos elementos que la mayoría de lenguajes de la actualidad soportan (arrays, punteros, clases...). Asi que el aprendiz de scripter -yo aún lo soy- deberia aprender unos pequeños trucos de programación para optimizar sus scripts.

-------------------------
1) Repetición de comandos
-------------------------
Para ahorrar espacio en el script no podemos repetir nunca las cosas varias veces, seria un uso de espacio inútil. Si tenemos que repetir un comando repetidas veces es mejor crear un alias que contenga dicho comando y utilizarlo todas las veces que haga falta. Por ejemplo:
Supongamos que tenemos este código en nuestro theme:
raw 1:*: {
echo $colour(info) -st *** Bienvenid@ al IRC, $1
haltdef
}

raw 2:*: {
echo $colour(info) -st *** Tu host es $5 bajo la versión $8
haltdef
}

raw 3:*: {
echo $colour(info) -st *** Servidor creado el día $6-
haltdef
}

Pues podriamos reducir el código bastante metiendo en un alias el comando echo con todos los parámetros y flags:

; Alias Einfo (Imprime en el Status con la fecha y en color de la info)
alias einfo { echo $colour(info) -st *** $1- }

; Códigos raw de bienvenida al IRC
raw 1:*: { einfo Bienvenid@ al IRC, $1 | haltdef }
raw 2:*: { einfo Tu host es $5 bajo la versión $8 | haltdef }
raw 3:*: { einfo Servidor creado el día $6- | haltdef }

---------------------------------
2) Limpieza del código VS espacio
---------------------------------
En programación siempre se quiere obtener la máxima limpieza en el código para poder detectar más fácilmente los errores y poder ampliar el código en el futuro si se necesitase. En scripting aparte de un código limpio necesitamos un código reducido. Yo personalmente intento que mi código esté limpio y cuando funciona a la perfección paso a reducirlo para que ocupe menos.

Es recomendable utilizar las llaves ({,}) y meter cada comando en una línea.
Los IF y los WHILE deberian ir siempre con llaves porque se ve el contenido del bucle mejor.
Tambien comentar/documentar todo lo que puedas con el punto y coma (;).

Cuando el código este listo puedes cambiar las llaves y utilizar pipes (|) para que el código quede más compacto.

Los comentarios no deberias quitarlos sobre todo si es un código muy denso, para su futura ampliación pero si los quitas reduciras espacio. Podrias quedarte tu con un código "maestro" ampliado y bien comentado y luego cuando distribuyas tu script das el código reducido.
También queda más limpio el código que tiene abundantes líneas en blanco para separar secciones.
El ejemplo anterior te sirve para comprobar a lo que me refiero.

---------------------------------
3) Archivos MRC en vez de INI
---------------------------------
Un archivo INI se compone de unas secciones y unos elementos:

[Seccion1]
Elemento11=Valor11
Elemento12=Valor12

[Seccion2]
Elemento21=Valor21
Elemento22=Valor22

En cambio un archivo MRC es un fichero de texto que simplemente se compone de lineas de texto separadas por caracteres de fin de linea y retorno de carro y que acaban con un carater de fin de fichero.

Cuando hacemos un archivo de script para por ejemplo los remotes, escribimos esto en la pantalla de remotes del mIRC:

on *:join:#: {
who $chan
msg $chan Hola a todos
}

Si lo grabamos en un MRC (o en general cualquier otra extensión pero esta es la más utilizada) al abrirlo con el notepad leeremos exactamente lo mismo pero si lo grabamos en un INI veremos esto:

[script]
n0=on *:join:#: {
n1= who $chan
n2= msg $chan Hola a todos
n3=}

Como te habras dado cuenta en un INI metemos más información que es realmente inútil.

-----------------------------
4) Hallar la fórmula general
-----------------------------
Pues hay veces que tenemos que repetir los comandos porque son muy parecidos pero sin llegar a ser iguales. En este caso no nos vale el uso de los alias porque aún así tendríamos que repetir el alias con parámetros de entrada distintos.
Por ejemplo:

%frase = $replace(%frase,$nombre(1),$letra(6))
%frase = $replace(%frase,$nombre(2),$letra(8))
%frase = $replace(%frase,$nombre(3),$letra(10))

Hallamos la fórmula general. Vemos que $nombre aumenta de 1 en 1 empezando por el 1. Y que $letra
aumenta de 2 en 2 empezando por el 6. Pues lo solucionamos con un while

var %i = 1, %j = 6
while (%i <= 3) {
%frase = $replace(%frase,$nombre(%i),$letra(%j))
inc %i
inc %j 2
}

El ejemplo está claro inicializamos las variables a 1 y a 6 y las reemplazamos en el comando de asignación. Después incrementamos las variables, la %i en 1 y la %j en 2. Utilizando esta técnica el programa es más legible, ocupa menos y es más fácil ampliarlo. Si necesitamos hacer más repeticiones cambiamos la condición del while al número que queramos.
Hay veces que queremos hacer lo siguiente:

echo -s Palabra 1: $1
echo -s Palabra 2: $2
echo -s Palabra 3: $3

y lo primero es que no sabemos cuantas palabras hay. Puess lo sabremos con $0 que devuelve el número de palabras. El cero suele significar en mIRC "el número de". Por ejemplo $nick($chan,0) devolverá el número de personas en el canal.

Weno pos el ejemplo anterior lo solucionaremos con while:

var %i 1
while (%i <= $0) {
echo -s Palabra %i $+ : $ [ $+ [ %i ] ]
inc %i
}

Lo único destacable de esto es el uso de $ [ $+ [ %i ] ]. Esto es una ñapa que hay que hacer con el mIRC porque no se puede hacer $%i ni $ $+ %i. Es una manera de evaluar en el orden deseado las variables y las funciones (identificadores).

-------------------------------
5) Aritmética entera y modular
-------------------------------
En la programación se utiliza mucho la aritmética entera y sus operaciones que son la división entera y el módulo (resto de la división entera).

Para hacer una división entera : $int($calc(a / b))
Para hacer el módulo : $calc(a % b)

A partir de ahora llamaré DIV a la division entera y MOD al módulo
Ahora que sabemos esto podemos hacer lo siguiente:

Dado un número por ejemplo: 17637

17637 DIV 1 = 17637 17637 MOD 1 = 0
17637 DIV 10 = 1763 17637 MOD 10 = 7
17637 DIV 100 = 176 17637 MOD 100 = 37
17637 DIV 1000 = 17 17637 MOD 1000 = 637
17637 DIV 10000 = 1 17637 MOD 10000 = 7637
17637 DIV 100000 = 0 17637 MOD 100000 = 17637

Unidades = N MOD 10
Decenas = (N MOD 100) DIV 10
Centenas = (N MOD 1000) DIV 100
Millares = (N MOD 10000) DIV 1000
Decenas de Millar = N DIV 10000

La estructura es discreta (finita) y hay que poner un final, en este caso el final lo hemos puesto en las decenas de millar pero la sucesión es bastante evidente. Hay un principio, un final y unas unidades intermedias y se ve claramente la progresión que sufren.
Si te das cuenta con DIV y MOD podemos sacar las unidades, decenas, centenas... de un número pero es cuando usamos el 10. Usamos es 10 porque estamos en el sistema decimal. Pero este sistema te puede servir tambien para hallar las horas, minutos y segundos en un sistema sexagesimal.

Por ejemplo dentro de un alias cuyo parámetro de entrada $1 son el número de segundos, podemos obtener cuantas semanas, dias, horas, minutos y segundos son:

var %seg $calc($1 % 60)
var %min $int($calc(($1 % 3600) / 60))
; 60 = nº de segundos en 1 minuto
var %hor $int($calc(($1 % 86400) / 3600)) ; 3600 = nº de segundos en
1 hora
var %dia $int($calc(($1 % 604800) / 86400)) ; 86400 = nº de segundos en
1 día
var %sem $int($calc($1 / 604800)) ; 604800 = nº de segundos en
1 semana

-----------------
6) Select Case
-----------------
En mIRC scripting no existe un select case o uh switch (estructura de control de alternativa múltiple) y una manera de simularla es mediante el goto. El goto es una instrucción prohibida en todos los lenguajes modernos de programación debido a que es posible crear un efecto lateral imprevisible. Actualmente con la programación procedural podemos evitar cualquier tipo de ruptura del flujo del programa. De todas formas en scripting el uso de goto es a veces deseable sobre todo para reducir espacio. Por ejemplo:

alias formato.circulo { return oOo $1- oOo }
alias formato.asterisco { return *+* $1- *+* }
alias formato.especial { return .: $1- :. }

Supongamos que tenemos estos alias y muchos mas similares podriamos reducirlos todos mediante un goto de la siguiente manera:

alias formato {
goto $1
:circulo | return oOo $2- oOo
:asterisco | return *+* $2- *+*
:especial | return .: $2- :.
}

-----------------
7) El uso de $+()
-----------------
Cuando concatenamos cadenas de caracteres tenemos que usar el operador $+. Pero ahorraremos espacio cuando sean muchos los elementos a concatenar con la función (identificador) $+().

| Con $+ Long | Con $+() Long
--------- + -------------------- ------- + ------------------ ----
2 Cadenas | CAD1 $+ CAD2 4 | $+(CAD1,CAD2) 5
3 Cadenas | CAD1 $+ CAD2 $+ CAD3 8 | $+(CAD1,CAD2,CAD3) 6
--------- + -------------------- ------- + ------------------ ----
n Cadenas
| CAD1 $+ ... $+ CADn (n-1)*4 | $+(CAD1,...,CADn) n+3

Long es la longitud en bytes sin contar las longitudes de las cadenas. Esta tabla nos quiere decir que $+ solo se debe usar cuando hay dos cadenas y $+() en el resto de los casos, ya que ganaremos una mejora en el espacio que ocupará el archivo.
--------------
B) Conclusión
--------------
Espero que os haya interesado y/o gustado este tutorial y si teneis cualquier comentario ya sea de cometer errores o que no hayais entendido algo mandad un e-mail a macmardigan@madrid.com. El mejor vademécum de scripting es el mirc.hlp, imprímelo y échale un vsitazo, siempre hay cosas interesantes y sencillas que puedas hacer.