Procedimentos e funções
Para programas maiores, divida o trabalho em pedaços com nome. Esses pedaços são procedimentos e funções.
Por que dividir em partes
Imagine um jogo com 500 linhas de código tudo no mesmo bloco. Achar onde está o desenho do jogador, a colisão, o som... vira um pesadelo. A solução é o procedimento: um pedaço de código com nome, que você chama de qualquer lugar do programa.
Procedimento: faz, mas não devolve
PROCEDURE NomeDoProcedimento(parametro1 AS TIPO, ...)
BEGIN
... comandos ...
END
DIGITE E VEJA
Programa 8.1 — Tabuada por procedimento
USES SCREEN 1
SCREEN 1
CLS
PROCEDURE MostraTabuada(n AS BYTE)
BEGIN
DIM i AS BYTE
FOR i = 1 TO 10
PRINT n; " X "; i; " = "; n * i
NEXT i
END
' Chamando o procedimento duas vezes
MostraTabuada(3)
PRINT ""
MostraTabuada(7)
Função: faz e devolve um valor
Uma função é como um procedimento, mas devolve um valor que você pode usar em uma expressão. Há duas formas de devolver, e você pode usar a que preferir:
' Forma 1 — RETURN expr: devolve e sai na hora
FUNCTION Quadrado(n AS WORD) AS WORD
BEGIN
RETURN n * n
END
' Forma 2 — estilo Pascal: atribui ao nome da função
FUNCTION Dobro(n AS BYTE) AS BYTE
BEGIN
Dobro = n * 2
END
' Usando as funções:
DIM total AS WORD
total = Quadrado(5) + Quadrado(12) ' = 25 + 144 = 169
PRINT Dobro(21) ' 42
Parâmetros e resultados podem ser BYTE, WORD, INT, BOOL ou STRING (só como parâmetro). Valores de 16 bits passam inteiros — Quadrado(200) devolve 40000 corretamente.
DICA
Procedimento ou função?
Use função quando o resultado da operação interessa (cálculo, conversão). Use procedimento quando o objetivo é um efeito colateral (desenhar na tela, tocar som).
RETURN antecipado
RETURN dentro de um laço encerra a função imediatamente — ótimo para buscas:
FUNCTION EhPrimo(n AS WORD) AS BOOL
BEGIN
DIM d AS WORD
IF n < 2 THEN
RETURN FALSE
END IF
d = 2
WHILE d * d <= n
IF n MOD d = 0 THEN
RETURN FALSE
END IF
d = d + 1
WEND
RETURN TRUE
END
Variáveis dentro de procedimentos
Os parâmetros são verdadeiramente locais: cada procedimento tem sua própria área na RAM, e um procedimento pode chamar outro sem perder seus argumentos.
Já um DIM escrito dentro do procedimento, na versão atual do compilador, ocupa a mesma área global das demais variáveis. Na prática: não repita nomes entre um DIM interno e uma variável do programa principal, ou uma vai sobrescrever a outra.
DIM contador AS BYTE = 99 ' global
PROCEDURE Conta()
BEGIN
DIM k AS BYTE ' nome diferente da global — seguro
FOR k = 1 TO 5
PRINT k
NEXT k
END
Conta() ' imprime 1,2,3,4,5
PRINT contador ' imprime 99
Parâmetros: como o chamador entrega informação
Os parâmetros entre parênteses na declaração são variáveis locais que recebem o valor passado na chamada. Cada chamada pode passar valores diferentes:
FUNCTION Maior(a AS WORD, b AS WORD) AS WORD
BEGIN
IF a > b THEN
RETURN a
END IF
RETURN b
END
DIM x AS WORD
x = Maior(100, 250) ' x = 250
x = Maior(x, 175) ' x continua 250
ATENÇÃO
Recursão: ainda não
Como cada procedimento tem uma única área de parâmetros, uma função que chama a si mesma sobrescreve os próprios argumentos. Use soluções iterativas (FOR/WHILE) — no MSX elas também são mais rápidas.
DIGITE E VEJA
Exemplo completo na IDE
O sample "Procedures & Functions (CSX)" reúne tudo deste capítulo: procedimentos com STRING, funções BYTE/WORD/BOOL, RETURN antecipado, função chamando função (MDC → MMC) e procedimento chamando procedimento.
Exercícios
- 8.1 — Escreva uma função
Dobro(n AS WORD) AS WORDque devolve o dobro. - 8.2 — Escreva uma função
EhPar(n AS BYTE) AS BOOL. Use-a em um IF.
Resumo do capítulo
- PROCEDURE faz algo; FUNCTION faz algo e devolve um valor.
- Todo bloco abre com
BEGINe fecha comEND. - Parâmetros são locais de verdade; um
DIMinterno ainda é global — use nomes distintos. - Devolva com
RETURN exprou comNomeDaFuncao = expr. - Divida programas grandes em muitas funções pequenas.
Trabalhando com STRING
Além de números, o CrossScript aceita variáveis do tipo STRING — textos que ficam guardados na memória e podem ser impressos, medidos e passados como parâmetro.
DIM msg AS STRING = "OLA MUNDO" ' buffer padrão (32 caracteres)
DIM nome AS STRING * 16 ' tamanho máximo 16
nome = "FULANO" ' atribui um novo texto
PRINT msg ' imprime a variável
PRINT "TAMANHO=", LEN(msg) ' LEN devolve o comprimento
Regras rápidas:
DIM x AS STRINGreserva um buffer de 32 bytes (mais o terminador).DIM x AS STRING * NreservaNbytes (máximo 250).x = "texto"copia o literal para dentro do buffer, respeitando o tamanho máximo.PRINT xeBPRINT col, lin, x, coraceitam a variável diretamente.LEN(x)devolve o número de caracteres antes do terminador (0..255).- Ainda não há concatenação (
s1 + s2) nem funções tipoLEFT$/MID$.
Exemplo: centralizar uma frase na tela
Este procedimento recebe a linha e a frase e calcula sozinho a coluna do meio (SCREEN 1 tem 32 colunas de largura):
USES SCREEN 1
SCREEN 1
CLS
PROCEDURE Centraliza(linha AS BYTE, frase AS STRING)
BEGIN
DIM col AS BYTE
col = (32 - LEN(frase)) / 2
LOCATE col, linha
PRINT frase
END
DIM titulo AS STRING = "CROSSSCRIPT MSX"
Centraliza(10, titulo)
Centraliza(12, "OLA MUNDO")
Centraliza(14, "PRESSIONE UMA TECLA")
NOTA — sintaxe do compilador
Todo PROCEDURE/FUNCTION deve abrir com BEGIN e fechar com END (sem END PROCEDURE / END FUNCTION).