Algumas linguagens possuem uma função que retorna o somatório de uma lista como, por exemplo: sum [1,2,3,4,5,6]. Se não temos, teremos que criar e, se desejarmos, poderemos criar com algumas características especiais. Eu posso querer criar uma função para o somatório e, em algumas ocasiões, desejo saber a média aritmética da lista. Se eu não especificar o tipo de dado, poderei efetuar o somatório de número, datas, horas e outras coisas que possam ser passíveis de serem somadas. Então, vamos lá.
Existem diversas formas de criar uma função em Rebo. Vamos utilizar Funct. A razão é que todas as variáveis criadas internamente serão locais e não influenciarão no restante do ambiente. Vejamos como ficaria:
1 rebol[
2 Title: "Somatório de séries."
3 Date: 28/10/2014
4 Version: 0.1
5 Autor: Guaracy
6 ]
7
8 sum: funct [
9 "Somatório de séries"
10 nums [block!]
11 /average "Retorna apenas a média do somatório da série"
12 /inject val "Valor para a inicialização do total"
13 ][
14 either inject [total: val][total: 0]
15 foreach n nums [total: total + n]
16 either average[total / length? nums][total]
17 ]
Nas linhas de 1 até 6 (poderia ser em uma linha mas dificultaria a legibilidade), temos o cabeçalho que é obrigatório. Poderia ser apenas no formato REBOL [] mas as informações podem auxiliar o programador podendo até verificar se a versão é compatível com seu programa.
O nome pela qual a função será chamada é sum: . O primeiro bloco após funct são as especificações da função. Colocamos uma string com uma descrição da função, o parâmetro nums que deverá ser um bloco ou ocorrerá um erro antes mesmo da função ser executada e dois refinadores. Se ela for chamada com /average, efetuará o somatório, dividirá pelo número de elementos e retorna a média aritmética em vez do somatório. Se /inject for especificado, deverá ser informado um valor que inicializará o total.
A linha 14 temos either que avalia uma expressão e retorna o primeiro bloco se a expressão for verdadeira ou o segundo se for falsa (como um if/then/else em outras linguagens). Se foi especificado /inject, o total será inicializado com o valor informado ou zero se não.
Na linha 15 temos o laço colocar em total a soma dos valores contidos no bloco informado para a função.
Na linha 16 verificamos se o retorno deve ser o total ou a média. O último resultado da função é o valor que será retornado (mas podemos utilizar return x se desejarmos outro valor).
A próxima parte seria integrar a nova função ao ambiente. Como coloquei no GitHub (poderia ser em um servidor da minha empresa ou outro qualquer) para demonstrar a integração com a internet. Basta executar do https://raw.githubusercontent.com/guaracy/rebol/master/extensoes/sum.r3 para que a nova função faça parte do nosso repertório. Poderia também baixar e gravar o arquivo no meu computador e executar do %sum.r3. Mas é necessário fazer isto sempre que executamos o Rebol? Não. É possível termos um arquivo rebol.r no diretório que executamos o Rebol com todas as instruções que desejamos que sejam feitas na inicialização do ambiente. Colocamos o do %sum.r3 no arquivo e sempre podemos contar com a nova função.
Já podemos ver como a nossa função funciona e o motivo das informações na definição da função.
>> help sum
USAGE:
SUM nums /average /inject val
DESCRIPTION:
Somatório de séries
SUM is a function value.
ARGUMENTS:
nums (block!)
REFINEMENTS:
/average -- Retorna apenas a média do somatório da série
/inject
val -- Valor para a inicialização do total
Podemos utilizar o somatório e/ou média com qualquer valor que faça sentido como números, horas, datas, pares ordenados, etc. Note que não faz sentido a média entre duas datas.
>> sum [1 2 3 4 5]
== 15
>> sum/inject [1 2 3 4 5] 10
== 25
>> sum/average [1 2 3 4 5]
== 3
>> sum/average/inject [1 2 3 4 5] 10
== 5
>> sum [10:20 10:30 10:00 5:15]
== 36:05
>> sum/average [10:20 10:30 10:00 5:15]
== 9:01:15
>> sum/average/inject [10:20 10:30 10:00 5:15] 5:00
== 10:16:15
>> sum [20/10/2014 10 10 5 2 6]
== 22-Nov-2014
>> sum [20/10/2014 23:25 8:55]
== 21-Oct-2014/8:20
>> sum [2x3 6 2 3 -1 2x1]
== 14x14
>> sum [20/10/2014 2.5]
== 22-Oct-2014/12:00
>> sum [2.3 3.5 4.2 12.9]
== 22.9