quarta-feira, 29 de outubro de 2014

Extendendo Rebol e GitHub

Resolvi criar um repositório no GiHub para integrar com o blog. Colocarei alguns programas, scripts e outros dados para facilitar os testes (como veremos adiante). Para quem não quer utilizar o Git, foi criada uma página para que todo o repositório possa ser baixado. Basta clicar nos botões para baixar o repositório compactado.

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

Nenhum comentário:

Postar um comentário